home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Eagles Nest BBS 8
/
Eagles_Nest_Mac_Collection_Disc_8.TOAST
/
Developer Tools⁄Additions
/
UFullTEView
/
UFullTEView.inc1.p
< prev
next >
Wrap
Text File
|
1990-10-18
|
115KB
|
4,029 lines
{ UFullTEView Version 2.3 }
{ ******** This is MacApp 2.0 Final !!!! Do NOT use with 2.0ß9 !!!! ******* }
{ Note to those who abhor special cases: This is not necessarily a unit whose }
{ code you really want to study at length.}
{$IFC MenuAccess}
CONST
kSubFont = FALSE; { Is "Font" a hierarchical submenu? }
kSubSize = FALSE; { Is "Size" a hierarchical submenu? }
kSubStyle = FALSE; { Is "Style" a hierarchical submenu? }
kSubJust = FALSE; { Is "Justification" a hierarchical submenu? }
cSizeChange = 3100; { Font-size commands }
cSizeBase = 3100;
{ 3101-3297 reserved for font sizes 1-197 pts. }
cSizeNextUp = 3298;
cSizeNextDown= 3299;
cSizeMin = 3109; { Minimum size listed in menu is 9 }
cSizeMax = 3124; { Maximum size listed in menu is 24 }
{ Command numbers to cover other stylistic changes }
cJustChange = 3300;
cFontChange = 3400;
{ Command numbers for the hierarchial menus, if present }
cStyle = 3501;
cSize = 3502;
cFont = 3503;
cJustLeft = 3608; { Justification commands }
cJustCenter = 3609;
cJustRight = 3610;
{ Constants for relative text resizing }
kSizeNextUp = 1;
kSizeNextDown = -1;
kRelSizeDelta = 4;
{ Cursor for italic text }
kSlantBeam = 3001;
{$ENDC} {MenuAccess}
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug & SubSuper}
{$S TENonRes}
PROCEDURE WrtSubSuperHandle(theSubSuperHandle: subSuperHandle);
VAR i: INTEGER;
PROCEDURE WrtSubSuper(num: INTEGER; theSubSuper: SubSuperElement);
BEGIN
WITH theSubSuper DO
WriteLn('Index: ', num, ' startChar: ', startChar,
' subSuper: ', ORD(subSuper),
' baseSize: ', baseSize);
END;
BEGIN
IF theSubSuperHandle = NIL THEN EXIT(WrtSubSuperHandle);
MoveHHi(Handle(theSubSuperHandle));
HLock(Handle(theSubSuperHandle));
WrLblHexLongint('SubSuperHandle', Ord(theSubSuperHandle));
WITH theSubSuperHandle^^ DO
BEGIN
WriteLn(' nRuns: ', nRuns);
WriteLn(' nullSubSuper: ', ORD(nullSubSuper), ' nullBaseSize: ', nullBaseSize);
FOR i := 0 TO nRuns DO
WrtSubSuper(i, runs[i])
END;
HUnlock(Handle(theSubSuperHandle));
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{$S TEInit}
PROCEDURE InitUFullTEView;
BEGIN
InitUTEView;
IF gDeadStripSuppression THEN
BEGIN
IF Member(TObject(NIL), TFullTEView) THEN;
{$IFC SubSuper}
IF Member(TObject(NIL), TFullSubSuperTEView) THEN;
{$ENDC}
END;
{$IFC NOT qNeedsScriptManager}
IF gConfiguration.hasScriptManager THEN
{$ENDC}
gNoScripts := GetEnvirons(smEnabled) <= 1
{$IFC NOT qNeedsScriptManager}
ELSE
gNoScripts := TRUE
{$ENDC};
gFullWordLeft := FALSE;
gFullWordRight := FALSE;
END;
{--------------------------------------------------------------------------------------------------}
{$IFC MenuAccess}
{$S TEOpen}
{$PUSH}{$IFC qTRACE}{$D+}{$ENDC}
PROCEDURE DrawCaretProc; External;
PROCEDURE DrawHighProc; External;
PROCEDURE InstallSlant(theTEHdl: TEHandle);
BEGIN
theTEHdl^^.caretHook := @DrawCaretProc;
theTEHdl^^.highHook := @DrawHighProc;
END;
FUNCTION IsItalic(thePt: Point; theTEPtr: TEPtr): BOOLEAN;
VAR pos: INTEGER;
theStyle: TextStyle;
lineHeight: INTEGER;
fontAscent: INTEGER;
theStyleHandle: TEStyleHandle;
theFullTEView: TFullTEView;
theVPt: VPoint;
BEGIN
theStyleHandle := GetStylHandle(TEHandle(@theTEPtr));
IF theStyleHandle <> NIL THEN
BEGIN
theFullTEView := TFullTEView(theStyleHandle^^.teRefCon);
IF thePt.v < 0 THEN { compensates for TEGetOffset bug on IIfx's }
pos := -1
ELSE
pos := TEGetOffset(thePt, TEHandle(@theTEPtr)) -1; { Assumes System 4.1 or greater! }
IF pos < 0 THEN
IsItalic := FALSE
ELSE
BEGIN
TEGetStyle(pos, theStyle, lineHeight, fontAscent, TEHandle(@theTEPtr));
IsItalic := italic IN theStyle.tsFace;
END
END
ELSE
IsItalic := italic IN theTEPtr^.txFace;
END;
{$POP}
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{$S TEOpen}
PROCEDURE TFullTEView.ITEView(itsDocument: TDocument; itsSuperView: TView; itsLocation, itsSize: VPoint;
itsHDeterminer, itsVDeterminer: SizeDeterminer; itsInset: Rect;
itsTextStyle: TextStyle; itsJustification: INTEGER; itsStyleType,
itsAutoWrap: BOOLEAN); OVERRIDE;
VAR theStyleHandle: TEStyleHandle;
BEGIN
{$IFC SubSuper}
fFullTypingCommand := NIL;
fAllowSubSuper := FALSE; {cannot use Subscript/Superscript menu commands}
fSubSuperHandle := NIL;
{$ENDC}
INHERITED ITEView(itsDocument, itsSuperView, itsLocation, itsSize,
itsHDeterminer, itsVDeterminer, itsInset, itsTextStyle,
itsJustification, itsStyleType, itsAutoWrap);
InstallSlant(fHTE);
fSelAnchor := fHTE^^.selStart;
fUpDown := FALSE;
{$IFC MenuAccess}
fMenuFont := TRUE; {can use Font menu commands}
fMenuSize := TRUE; {can use Size menu commands}
fMenuStyle := TRUE; {can use Style menu commands}
fMenuJust := FALSE; {cannot use Justification menu commands}
fMenuUpDown := fMenuSize; {there are menu commands to step the FontSize}
fAllowedStyles := [bold, italic, underline];
IF fStyleType = kWithStyle THEN
BEGIN
theStyleHandle := GetStylHandle(fHTE);
FailNil(theStyleHandle);
theStyleHandle^^.teRefCon := ORD(SELF);
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TEOpen}
PROCEDURE TFullTEView.IRes(itsDocument: TDocument; itsSuperView: TView; VAR itsParams: Ptr); OVERRIDE;
VAR theStyleHandle: TEStyleHandle;
BEGIN
{$IFC SubSuper}
fFullTypingCommand := NIL;
fAllowSubSuper := FALSE; {cannot use Subscript/Superscript menu commands}
fSubSuperHandle := NIL;
{$ENDC}
INHERITED IRes(itsDocument, itsSuperView, itsParams);
InstallSlant(fHTE);
fSelAnchor := fHTE^^.selStart;
fUpDown := FALSE;
{$IFC MenuAccess}
fMenuFont := TRUE; {can use Font menu commands}
fMenuSize := TRUE; {can use Size menu commands}
fMenuStyle := TRUE; {can use Style menu commands}
fMenuJust := FALSE; {cannot use Justification menu commands}
fMenuUpDown := fMenuSize; {there are menu commands to step the FontSize}
fAllowedStyles := [bold, italic, underline];
IF fStyleType = kWithStyle THEN
BEGIN
theStyleHandle := GetStylHandle(fHTE);
FailNil(theStyleHandle);
theStyleHandle^^.teRefCon := ORD(SELF);
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.WordBounds(charPos: Integer; VAR wordStart, wordEnd: Integer): BOOLEAN;
{ charPos is the offset of a specific character in the text }
{ Returns: TRUE iff that character is part of a word }
{ wordStart = offset of first character of the word }
{ wordEnd = offset of final character of the word }
{ Note: these are CHARACTER offsets, not CURSOR POSITIONS. }
VAR
wordChars, alphaNum: SET of CHAR;
chLeft, chRight: CHAR;
offs: OffSetTable;
i: INTEGER;
FUNCTION GetChar(charPos: Integer): CHAR;
BEGIN
GetChar := CHAR(Ptr(Ord4(fText^) + charPos)^);
END;
FUNCTION ValidBreak(iPos: Integer): BOOLEAN;
{ Returns TRUE iff the CURSOR POSITION iPos does not fall within a word. }
BEGIN
ValidBreak := TRUE;
if (iPos > 0) & (iPos < fHTE^^.teLength) then
BEGIN
chLeft := GetChar(iPos-1);
chRight := GetChar(iPos);
if (chLeft IN wordChars) & (chRight IN wordChars) then
ValidBreak := FALSE
else if (chLeft = '.') | (chLeft = ',') then
BEGIN
if chRight IN ['0'..'9'] then
if chLeft = '.' then
ValidBreak := FALSE
else if (iPos > 1) & (GetChar(iPos-2) IN ['0'..'9']) then
ValidBreak := FALSE;
END
else if (chLeft = '''') & (chRight IN alphaNum) & (iPos > 1)
& (GetChar(iPos-2) IN alphaNum) then
ValidBreak := FALSE
else if (chRight = '.') | ((chRight = ',') & (chLeft IN ['0'..'9'])) then
BEGIN
if (iPos < fHTE^^.teLength-1) & (GetChar(iPos+1) IN ['0'..'9']) then
ValidBreak := FALSE;
END
else if (chRight = '''') & (chLeft IN alphaNum) & (iPos < fHTE^^.teLength-1)
& (GetChar(iPos+1) IN alphaNum) then
ValidBreak := FALSE;
END;
END;
BEGIN
wordStart := charPos;
wordEnd := charPos;
if (charPos < 0) | (charPos > fHTE^^.teLength-1) then
BEGIN
WordBounds := FALSE;
EXIT(WordBounds);
END;
if gNoScripts then
BEGIN {Based on Apple Human Interface Guidelines…}
alphaNum := ['A'..'Z','a'..'z','Ä'..'ü','ß'..'™','Æ','Ø','µ'..'ø',' '..'œ','ÿ','0'..'9'];
wordChars := alphaNum + ['$','¢','£','¥','%','-'];
chLeft := GetChar(charPos);
if chLeft IN wordChars then
WordBounds := TRUE
else if (chLeft = '.') | (chLeft = ',') | (chLeft = '''') then
WordBounds := NOT ValidBreak(charPos+1);
while NOT ValidBreak(wordStart) do wordStart := wordStart - 1;
while NOT ValidBreak(wordEnd+1) do wordEnd := wordEnd + 1;
END
else { if a non-Roman script is present, use the Script Manager routines }
BEGIN
REPEAT
i := CharByte(fText^, charPos);
charPos := charPos + 1;
UNTIL (i = 0) | (i = 1);
charPos := charPos -1;
FindWord(fText^, fHTE^^.teLength, charPos, TRUE, NIL, offs);
wordStart := MIN(offs[0].offFirst, offs[0].offSecond - 1);
wordEnd := MAX(offs[0].offFirst, offs[0].offSecond - 1);
WordBounds := (wordStart < wordEnd) | (CharType(fText^, wordStart) MOD 8 <> smCharPunct);
END
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.TripleBounds(charPos: Integer;
VAR tripleStart, tripleEnd: Integer): BOOLEAN;
{ Override this method if you want triple-click to select a sentence, }
{ a line, the entire field, whatever. }
{ charPos is the offset of a specific character in the text }
{ Returns: TRUE iff that character is part of a "sentence" }
{ tripleStart = offset of first character of the "sentence" }
{ tripleEnd = offset of final character of the "sentence" }
{ Note: these are CHARACTER offsets, not CURSOR POSITIONS. }
BEGIN
TripleBounds := WordBounds(charPos, tripleStart, tripleEnd);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoCommandKey(ch: CHAR; VAR info: EventInfo): TCommand; OVERRIDE;
{ unlike 2.0ß9 version of this method, we don't have to worry about "+" really
being Shift-"=", etc. For further important details, see
TApplication.DoCommandKey. }
VAR c: cmdNumber;
BEGIN
IF (ch >= chLeft) & (ch <= chDown) THEN
DoCommandKey := DoKeyCommand(ch, 0, info)
ELSE
BEGIN
DoCommandKey := gNoChanges;
fUpDown := FALSE;
{$IFC MenuAccess}
IF ch IN ['<','>'] THEN
IF fMenuSize THEN { this works even if NOT fMenuUpDown }
IF ch = '<' THEN
DoCommandKey := DoMenuCommand(cSizeNextDown)
ELSE
DoCommandKey := DoMenuCommand(cSizeNextUp)
ELSE
gApplication.Beep(1)
ELSE
{$ENDC}
DoCommandKey := INHERITED DoCommandKey(ch,info);
END
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoKeyCommand(ch: Char; aKeyCode: INTEGER; VAR info: EventInfo): TCommand; OVERRIDE;
VAR
handledCharacter, selecting: Boolean;
goToPos, i, oldLine, nonAnchor: Integer;
expanding: Boolean;
newStart, newEnd: Integer;
towardStart: Boolean;
aVPoint: VPoint;
FUNCTION FindLine(selPos: Integer): Integer;
VAR
i: Integer;
BEGIN
with fHTE^^ do
BEGIN
if nLines <= 1 then
FindLine := 0
else
BEGIN
i := nLines-1;
while lineStarts[i] > selPos do i := i - 1;
FindLine := i;
END;
END;
END;
FUNCTION FindLineStart: Integer;
BEGIN
with fHTE^^ do
if nLines <= 1 then
FindLineStart := 0
else
FindLineStart := lineStarts[ FindLine(nonAnchor) ];
END;
FUNCTION FindLineEnd: Integer;
VAR
i: Integer;
BEGIN
with fHTE^^ do
BEGIN
if nLines <= 1 then
FindLineEnd := teLength
else
BEGIN
i := nLines-1;
while lineStarts[i] > nonAnchor do i := i - 1;
if i < nLines-1 then
FindLineEnd := lineStarts[i+1] - 1
else
FindLineEnd := teLength;
END;
END;
END;
BEGIN
DoKeyCommand := gNoChanges;
handledCharacter := FALSE;
goToPos := fHTE^^.selStart;
selecting := FALSE;
if (ch <> chUp) & (ch <> chDown) then fUpDown := FALSE;
if (ch = chLeft) | (ch=chRight) then
BEGIN
towardStart := (ch = chLeft);
if NOT gNoScripts then
if GetScript(GetEnvirons(smKeyScript), smScriptRight) <> 0 then
towardStart := NOT towardStart;
END
else
towardStart := FALSE;
with fHTE^^ do
BEGIN
if selStart = selEnd then fSelAnchor := selStart;
if fSelAnchor < 0 then
if (ch = chUp) | (towardStart) then
fSelAnchor := selEnd
else
fSelAnchor := selStart;
if fSelAnchor = selEnd then nonAnchor := selStart
else nonAnchor := selEnd;
END;
if (ch = chUp) & (FindLine(nonAnchor) = 0) then
BEGIN {same as Cmd-Up}
selecting := info.theShiftKey;
handledCharacter := TRUE;
goToPos := 0;
fUpDown := FALSE;
END
else if (ch = chDown) & (FindLine(nonAnchor) = fHTE^^.nLines - 1) then
BEGIN {same as Cmd-Down}
selecting := info.theShiftKey;
handledCharacter := TRUE;
goToPos := fHTE^^.teLength;
fUpDown := FALSE;
END;
if (NOT handledCharacter) & (ch >= chLeft) & (ch <= chDown) then
with fHTE^^ do
BEGIN
HLock(handle(fHTE));
selecting := info.theShiftKey;
handledCharacter := TRUE;
if info.theCmdKey then { Actually, Cmd-Up & Cmd-Down differ from }
BEGIN { the Human Interface Guidelines. Let me }
if ch = chUp then goToPos := 0 { know if you think this should be modified!}
else if ch = chDown then goToPos := teLength
else if towardStart then goToPos := FindLineStart
else goToPos := FindLineEnd;
fUpDown := FALSE;
END
else if (ch = chUp) | (ch = chDown) then
BEGIN
if NOT fUpDown then
BEGIN
fUpDown := TRUE;
i := OffsetToPt(nonAnchor).h; { OffsetToPt might move memory, so }
fUpDownH := i; { we'll be paranoid (by using "i") }
END;
if lineHeight < 0 then {styled text}
BEGIN
i := FindLine(nonAnchor);
i := TEGetHeight(LONGINT(i), LONGINT(i), fHTE);
END
else
i := lineHeight;
if ch = chUp then i := -i;
aVPoint.v := OffsetToPt(nonAnchor).v + i;
aVPoint.h := fUpDownH;
goToPos := PtToOffset(aVPoint);
i := FindLine(nonAnchor);
if (ch = chUp) & (goToPos = lineStarts[i]) then
goToPos := goToPos - 1
else if (ch = chDown) & (FindLine(goToPos) = i+2) then
goToPos := goToPos + 1;
END
else if info.theOptionKey {& ((ch = chLeft) | (ch = chRight))} then
BEGIN
if selecting then
if towardStart then expanding := (nonAnchor <= fSelAnchor)
else expanding := (nonAnchor >= fSelAnchor)
else
expanding := TRUE;
goToPos := nonAnchor;
if NOT expanding then
if towardStart then
BEGIN
newEnd := goToPos;
while (goToPos > fSelAnchor) & ( (NOT WordBounds(goToPos, newStart, newEnd))
| (newEnd+1 >= nonAnchor) ) do goToPos := newStart - 1;
if goToPos <= fSelAnchor then
BEGIN
expanding := TRUE;
goToPos := fSelAnchor;
END
else goToPos := newEnd + 1;
END
else {NOT towardStart}
BEGIN
newStart := goToPos;
while (goToPos < fSelAnchor) & ( (NOT WordBounds(goToPos, newStart, newEnd))
| (newStart <= nonAnchor) ) do goToPos := newEnd + 1;
if goToPos >= fSelAnchor then
BEGIN
expanding := TRUE;
goToPos := fSelAnchor;
END;
END;
if expanding then
if towardStart then
BEGIN
i := goToPos;
newStart := goToPos;
while (goToPos > 0) & ( (NOT WordBounds(goToPos, newStart, newEnd))
| (newStart >= i) ) do goToPos := goToPos - 1;
goToPos := MIN(goToPos,newStart)
END
else {NOT towardStart}
BEGIN
newEnd := goToPos;
i := fHTE^^.teLength - 1;
while (goToPos < i) & NOT WordBounds(goToPos+1, newStart, newEnd)
do goToPos := goToPos + 1;
goToPos := MAX(goToPos,newEnd) + 1;
END;
END
else if info.theShiftKey | (selStart = selEnd) {& ((ch = chLeft) | (ch = chRight))} then
BEGIN
if towardStart then
i := -1
else
i := +1;
goToPos := MIN(MAX(nonAnchor + i, 0), teLength);
END
else {selStart <> selEnd & ((ch = chLeft) | (ch = chRight))}
BEGIN
if towardStart then
goToPos := selStart
else
goToPos := selEnd;
END;
HUnlock(handle(fHTE));
END;
if handledCharacter then
BEGIN
DoneTyping;
if selecting then
SetSelection(MIN(goToPos,fSelAnchor), MAX(goToPos,fSelAnchor), kRedraw)
else
SetSelection(goToPos, goToPos, kRedraw);
END
else
BEGIN
{$IFC SubSuper}
DoKeyCommand := OldDoKeyCommand(ch, aKeyCode, info);
{$ELSEC}
DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
{$ENDC}
with fHTE^^ do
if selecting then
SetSelection(MIN(selStart,fSelAnchor), MAX(selEnd,fSelAnchor), kRedraw)
else
if selStart = selEnd then fSelAnchor := selStart;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
{$PUSH}{$IFC qTRACE}{$D+}{$ENDC}
PROCEDURE DoHigh(theTEPtr: TEPtr; pos1, pos2: INTEGER); EXTERNAL;
PROCEDURE TFullTEView.DrawSelection(newStart, newEnd: INTEGER);
VAR theRect: Rect;
BEGIN
WITH fHTE^^ DO
IF (newStart <> selStart) | (newEnd <> selEnd) THEN
IF (newStart >= newEnd) | (selStart >= selEnd) THEN
TESetSelect(newStart, newEnd, fHTE)
ELSE
{ TESetSelect(newStart, newEnd, fHTE); <-- This flashes too much! }
BEGIN
GetQDExtent(theRect);
theRect.left := theRect.left + fInset.left;
theRect.right := theRect.right - fInset.right;
ClipFurtherTo(theRect, 0, 0); { <-- avoid highlighting the insets }
HLock(Handle(fHTE));
IF newStart <> selStart THEN
DoHigh(fHTE^, MIN(newStart, selStart), MAX(newStart, selStart));
IF newEnd <> selEnd THEN
DoHigh(fHTE^, MIN(newEnd, selEnd), MAX(newEnd, selEnd));
HUnlock(Handle(fHTE));
selStart := newStart;
selEnd := newEnd;
END;
END;
{$POP}
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.SetSelection(NewSelStart, NewSelEnd: INTEGER; redraw: BOOLEAN);
BEGIN
with fHTE^^ do
BEGIN
IF redraw & Focus THEN
BEGIN
DrawSelection(MAX(NewSelStart, 0), MIN(NewSelEnd, fHTE^^.teLength));
SynchView(TRUE);
END
ELSE
SetSelect(MAX(NewSelStart, 0), MIN(NewSelEnd, fHTE^^.teLength), fHTE);
if NewSelStart = NewSelEnd then fSelAnchor := NewSelStart;
END;
fSpecsChanged := TRUE;
{$IFC SubSuper}
if fAllowSubSuper then
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := undefined;
nullBaseSize := 0;
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoMouseCommand(VAR theMouse: Point; VAR info: EventInfo;
VAR hysteresis: Point): TCommand; OVERRIDE;
VAR
aTEMouseCommand: TFullTEMouseCommand;
aRect, bRect: Rect;
i, j: Integer;
itsDown: Boolean;
BEGIN
IF Focus & IsVisible THEN
BEGIN
pCurrTEView := SELF;
DoneTyping; { Mousedown terminates the Typing command }
fSpecsChanged := TRUE;
{ pAutoScrolled := FALSE; { Will get set to true by AutoScrollTEView }
fUpDown := FALSE;
NEW(aTEMouseCommand);
FailNil(aTEMouseCommand);
aTEMouseCommand.ITEMouseCommand(SELF, info.theShiftKey);
DoMouseCommand := aTEMouseCommand;
{ IF pAutoScrolled THEN { If we autoscrolled… }
{ BEGIN
{ gApplication.InvalidateFocus; { …force a re-focus }
{ IF Focus THEN;
{ END;
} END;
END;
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
FUNCTION TFullTEView.DoMakeEditCommand(aCmdNumber: CmdNumber): TTECommand; OVERRIDE;
VAR
aCutCopyCommand: TFullTECutCopyCommand; {The only difference }
aPasteCommand: TFullTEPasteCommand; { is in using the "Full" }
aClearCommand: TFullTECommand; { TTECommand classes. }
BEGIN
CASE aCmdNumber OF
cCut, cCopy:
BEGIN
New(aCutCopyCommand);
FailNIL(aCutCopyCommand);
aCutCopyCommand.ITECutCopyCommand(SELF, aCmdNumber);
DoMakeEditCommand := aCutCopyCommand;
END;
cPaste:
BEGIN
New(aPasteCommand);
FailNIL(aPasteCommand);
aPasteCommand.ITEPasteCommand(SELF);
DoMakeEditCommand := aPasteCommand;
END;
cClear:
BEGIN
New(aClearCommand);
FailNIL(aClearCommand);
aClearCommand.ITECommand(SELF, aCmdNumber, TRUE);
DoMakeEditCommand := aClearCommand;
END;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.PtToOffset(point: VPoint): INTEGER;
{ Note: the following converts view coordinates to cursor position. }
{ If Script Manager is present, then so must be Styled TextEdit, and }
{ as the Script Manager should have patched TEGetOffset, we don't have }
{ to deal explicitly with scripts here. }
{ Note #2: if there's no Styled TextEdit, and if the field is not left- }
{ justified, the following code will screw up. Let me know if you care }
{ about such things. }
VAR
pos, lineNo, lineStart: INTEGER;
nextLine, height, horiz: INTEGER;
aRect: Rect;
theQDPt: Point;
BEGIN
IF Focus THEN { Formerly we assumed focused, but }
{ I've since encountered situations }
BEGIN { where that may not be true. }
{$IFC NOT qNeedsStyleTextEdit}
IF gConfiguration.hasStyleTextEdit THEN
{$ENDC}
BEGIN
theQDPt := ViewToQDPt(point);
IF theQDPt.v < 0 THEN { TEGetOffset returns the wrong value on a }
PtToOffset := 0 { IIfx if the v coordinate is negative. }
ELSE
PtToOffset := TEGetOffset(theQDPt, fHTE)
END
{$IFC NOT qNeedsStyleTextEdit}
ELSE
BEGIN
GetQDExtent(aRect);
height := aRect.bottom - fInset.bottom;
horiz := ViewToQDPt(point).h - fInset.left;
HLock(Handle(fHTE));
WITH fHTE^^ DO
BEGIN
TextFont(txFont); { <-- I wouldn't have thought }
TextFace(txFace); { <-- that we'd need these, }
TextSize(txSize); { <-- but it turns out we do! }
HLock(Handle(hText)); {<- necessary???}
lineNo :=
MIN( MAX(ViewToQDPt(point).v - fInset.top, 0), height)
DIV lineHeight;
lineStart := lineStarts[lineNo];
if lineNo = nLines - 1 then
nextLine := teLength + 1
else
nextLine := lineStarts[lineNo + 1];
pos := lineStart + 1;
WHILE (pos < nextLine)
& (TextWidth(hText^, lineStart, pos-lineStart)
- (CharWidth(CHAR(PTR(ORD4(hText^) + pos - 1)^)) DIV 2)
<= horiz) DO
BEGIN
pos := pos + 1;
END;
PtToOffset := pos - 1;
HUnlock(Handle(hText));
END;
HUnlock(Handle(fHTE));
END
{$ENDC};
END
else
PtToOffset := 0; { ...as good a value to return as any }
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.OffsetToPt(offset: Integer): VPoint;
{ Note: the following converts cursor position to view coordinates. }
{ If Script Manager is present, then so must be Styled TextEdit, and }
{ as the Script Manager should have patched TEGetOffset, we don't have }
{ to deal explicitly with scripts here. }
{ Note #2: if there's no Styled TextEdit, and if the field is not left- }
{ justified, the following code will screw up. Let me know if you care }
{ about such things. }
VAR
lineNo, lineStart, height: INTEGER;
thePoint: Point;
theStyle: TextStyle;
ascent: INTEGER;
BEGIN
if Focus then { Formerly we assumed focused, but }
{ I've since encountered situations }
BEGIN { where that may not be true. }
{$IFC NOT qNeedsStyleTextEdit}
if gConfiguration.hasStyleTextEdit then
{$ENDC}
BEGIN
TEGetStyle(offset, theStyle, height, ascent, fHTE);
if fHTE^^.teLength <= 0 then {Work-around for TEGetPoint bug (through System 6.0.4:}
SetPt(thePoint, fInset.left, fInset.top)
else
thePoint := TEGetPoint(offset, fHTE);
thePoint.v := thePoint.v - height + ascent;
END
{$IFC NOT qNeedsStyleTextEdit}
else
BEGIN
HLock(Handle(fHTE));
WITH fHTE^^ DO
BEGIN
TextFont(txFont); { <-- I wouldn't have thought }
TextFace(txFace); { <-- that we'd need these, }
TextSize(txSize); { <-- but it turns out we do! }
HLock(Handle(hText)); {<- necessary???}
lineNo := 0;
while (lineNo < nLines - 1) & (lineStarts[lineNo + 1] <= offset) DO
lineNo := lineNo + 1;
lineStart := lineStarts[lineNo];
thePoint.v := fInset.top + (lineNo * lineHeight) + fontAscent;
thePoint.h := fInset.left + TextWidth(hText^, lineStart, offset-lineStart);
HUnlock(Handle(hText));
END;
HUnlock(Handle(fHTE));
END
{$ENDC};
QDToViewPt(thePoint, OffsetToPt);
END
else
OffsetToPt := gZeroVpt; { ...as good a value to return as any }
END;
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC MenuAccess}
{--------------------------------------------------------------------------------------------------}
{$IFC SubSuper}
{$S FullTERes}
FUNCTION GetIndex(theSubSuper: SubSuperHandle; charPos: INTEGER): INTEGER;
VAR i: INTEGER;
BEGIN
WITH theSubSuper^^ DO
BEGIN
charPos := MIN(MAX(charPos, 0), runs[nRuns].startChar - 1);
i := 0;
WHILE runs[i].startChar < charPos DO
i := i + 1;
if runs[i].startChar > charPos then
i := i - 1;
GetIndex := i;
END;
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.DoSetupMenus; OVERRIDE;
VAR
hasStyle: BOOLEAN;
checkPlain: BOOLEAN;
checkSize: BOOLEAN;
checkFont: BOOLEAN;
continStyle: BOOLEAN;
aBoolean: BOOLEAN;
just: INTEGER;
item: INTEGER;
fnt: INTEGER;
c: INTEGER;
aMode: INTEGER;
aFace: Style;
aMenuHandle: MenuHandle;
aName: Str255;
aStyle: TextStyle;
theFont: INTEGER;
theSize: INTEGER;
startOfSelection: INTEGER;
endOfSelection: INTEGER;
aStr255: Str255;
{$IFC SubSuper}
bMode: INTEGER;
bStyle: TextStyle;
theSubSuper: SubOrSuper;
theBaseSize: INTEGER;
continSubSuper: BOOLEAN;
index: INTEGER;
loopFlag: BOOLEAN;
{$ENDC}
BEGIN
INHERITED DoSetupMenus;
hasStyle := gConfiguration.hasStyleTextEdit;
{$IFC NOT qNeedsStyleTextEdit}
IF NOT hasStyle THEN
BEGIN
aStyle := fTextStyle;
checkPlain := aStyle.tsFace = [];
checkFont := TRUE;
continStyle := TRUE;
END
ELSE
{$ENDC}
BEGIN
WITH fHTE^^ DO
BEGIN
startOfSelection := selStart;
endOfSelection := selEnd;
END;
aMode := doFace;
{$IFC SubSuper}
if fAllowSubSuper then
continSubSuper := ContinuousSubSuper(startOfSelection, endOfSelection, theSubSuper, theBaseSize)
else
BEGIN
continSubSuper := TRUE;
theSubSuper := normal;
END;
{$ENDC}
checkPlain := ContinuousStyle(startOfSelection, endOfSelection, aMode, aStyle)
& (aStyle.tsFace = [])
{$IFC SubSuper}
& continSubSuper & (theSubSuper = normal)
{$ENDC};
aMode := doAll;
aStyle.tsFace := [bold, italic, underline, outline, shadow, extend, condense];
aBoolean := ContinuousStyle(startOfSelection, endOfSelection, aMode, aStyle);
checkFont := BAND(aMode, doFont) <> 0;
continStyle := BAND(aMode, doFace) <> 0;
{$IFC SubSuper}
IF ( BAND(aMode, doSize) = 0 ) & ( NOT continSubSuper ) THEN
BEGIN
loopFlag := FALSE;
FOR index := GetIndex(fSubSuperHandle, startOfSelection) TO GetIndex(fSubSuperHandle, endOfSelection - 1) DO
BEGIN
WITH fSubSuperHandle^^.runs[index] DO
IF subSuper = normal THEN
BEGIN
bMode := doSize;
aBoolean := ContinuousStyle(MAX(startChar, startOfSelection),
MIN(fSubSuperHandle^^.runs[index + 1].startChar, endOfSelection),
bMode, bStyle);
if BAND(bMode, doSize) <> 0 then
theBaseSize := bStyle.tsSize
else
theBaseSize := -1;
END
ELSE
theBaseSize := baseSize;
IF theBaseSize = 0 THEN theBaseSize := GetDefFontSize;
IF NOT loopFlag THEN
BEGIN
IF theBaseSize = -1 THEN Leave;
aStyle.tsSize := theBaseSize;
loopFlag := TRUE;
END
ELSE IF theBaseSize <> aStyle.tsSize THEN Leave;
END;
IF ( theBaseSize = aStyle.tsSize ) & ( theBaseSize <> -1 ) THEN aMode := aMode + doSize;
END;
{$ENDC}
END;
if fMenuFont then
BEGIN
aMenuHandle := GetMHandle(mFont);
GetFontName(aStyle.tsFont, aName); { Get real font number in case tsFont is }
GetFNum(aName, theFont); { …the system or application font. }
FOR item := 1 TO CountMItems(aMenuHandle) DO
BEGIN
{ There can be more than 31 menu entries with scrolling menus, but trying to enable
an item with number > 31 is bad news. If the menu itself is enabled (which it
will be in MacApp if any of the first 31 items is enabled), then the extras
will always be enabled. }
IF item <= 31 THEN
EnableItem(aMenuHandle, item);
IF checkFont THEN
BEGIN
GetItem(aMenuHandle, item, aName);
GetFNum(aName, fnt);
CheckItem(aMenuHandle, item, fnt = theFont);
END;
END;
END;
if fMenuJust then
BEGIN
just := fJustification;
EnableCheck(cJustLeft, TRUE, (just = teForceLeft));
EnableCheck(cJustCenter, TRUE, (just = teJustCenter));
EnableCheck(cJustRight, TRUE, (just = teJustRight));
END;
{$IFC NOT qNeedsHierarchicalMenus}
IF gConfiguration.hasHierarchicalMenus THEN
{$ENDC}
BEGIN
if kSubStyle then Enable(cStyle, TRUE);
if kSubSize then Enable(cSize, TRUE);
if kSubFont then Enable(cFont, TRUE);
END;
if fMenuStyle then
BEGIN
aFace := aStyle.tsFace;
EnableCheck(cPlainText, TRUE, checkPlain);
if bold IN fAllowedStyles then EnableCheck(cBold, TRUE, continStyle & (bold IN aFace));
if italic IN fAllowedStyles then EnableCheck(cItalic, TRUE, continStyle & (italic IN aFace));
if underline IN fAllowedStyles then EnableCheck(cUnderline, TRUE, continStyle & (underline IN aFace));
if outline IN fAllowedStyles then EnableCheck(cOutline, TRUE, continStyle & (outline IN aFace));
if shadow IN fAllowedStyles then EnableCheck(cShadow, TRUE, continStyle & (shadow IN aFace));
if condense IN fAllowedStyles then EnableCheck(cCondense, TRUE, continStyle & (condense IN aFace));
if extend IN fAllowedStyles then EnableCheck(cExtend, TRUE, continStyle & (extend IN aFace));
{$IFC SubSuper}
if fAllowSubSuper then
BEGIN
EnableCheck(cSubscript, TRUE, continSubSuper & (theSubSuper = subscript));
EnableCheck(cSuperscript, TRUE, continSubSuper & (theSubSuper = superscript));
END;
{$ENDC}
END;
if fMenuSize then
BEGIN
{$IFC SubSuper}
if continSubSuper & (theSubSuper <> normal) then
theSize := theBaseSize
else
{$ENDC}
theSize := aStyle.tsSize;
if theSize = 0 then theSize := GetDefFontSize;
FOR c := cSizeMin TO cSizeMax DO
BEGIN
IF hasStyle & (BAND(aMode, doSize) = 0) THEN
checkSize := FALSE
ELSE
checkSize := (c - cSizeBase) = theSize;
EnableCheck(c, TRUE, checkSize);
IF RealFont(aStyle.tsFont,c - cSizeBase) THEN
aFace := [outline]
ELSE
aFace := [];
SetStyle(c, aFace);
END;
if fMenuUpDown then
BEGIN
Enable(cSizeNextUp, TRUE);
Enable(cSizeNextDown, TRUE);
END;
END;
fSpecsChanged := FALSE;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; OVERRIDE;
VAR
aName: Str255;
menu: INTEGER;
item: INTEGER;
newStyle: TextStyle;
aStyleItem: StyleItem;
PROCEDURE DoSizeChange(base: CmdNumber);
BEGIN
newStyle.tsSize := aCmdNumber - base;
{$IFC SubSuper}
IF fAllowSubSuper THEN
DoMenuCommand := DoMakeFullStyleCommand(newStyle, cSizeChange, doSize)
ELSE
{$ENDC}
DoMenuCommand := DoMakeStyleCommand(newStyle, cSizeChange, doSize);
END;
PROCEDURE DoRelSizeChange(upDown: INTEGER);
VAR theSize, aMode, maximumFontSize: INTEGER;
startOfSelection, endOfSelection: INTEGER;
BEGIN
maximumFontSize := 127; { <- will change for System 7.0 ! }
WITH fHTE^^ DO
BEGIN
startOfSelection := selStart;
endOfSelection := selEnd;
END;
aMode := doSize;
if ContinuousStyle(startOfSelection, endOfSelection, aMode, newStyle) then
BEGIN
theSize := newStyle.tsSize;
if theSize = 0 then theSize := GetDefFontSize;
if upDown = kSizeNextUp then
if (theSize + cSizeBase < cSizeMax)
& ((theSize *3) DIV 2 + cSizeBase >= cSizeMin) then
BEGIN
FOR theSize := theSize + 1 TO cSizeMax - cSizeBase DO
if CmdEnabled(theSize + cSizeBase) then Leave;
END
else
theSize := (theSize * 3) DIV 2
else if (theSize + cSizeBase > cSizeMin)
& ((theSize + theSize) DIV 3 + cSizeBase <= cSizeMax) then
BEGIN
FOR theSize := theSize - 1 DOWNTO cSizeMin - cSizeBase DO
if CmdEnabled(theSize + cSizeBase) then Leave;
END
else
theSize := (theSize + theSize) DIV 3;
if (theSize > 1) & (theSize < maximumFontSize) then
BEGIN
newStyle.tsSize := theSize;
{$IFC SubSuper}
IF fAllowSubSuper THEN
DoMenuCommand := DoMakeFullStyleCommand(newStyle, cSizeChange, doSize)
ELSE
{$ENDC}
DoMenuCommand := DoMakeStyleCommand(newStyle, cSizeChange, doSize);
END;
END
else
{ The following is a bit of a cop-out. It would be easy enough to loop }
{ through the selection's continuous-size runs, applying the above code }
{ to each in turn. However if that's all we did, then each run would be }
{ resized by a separate StyleCommand, and only the final one would be }
{ undoable. One *could* create a new class of command objects to do this }
{ correctly; let me know if you're volunteering. }
BEGIN
newStyle.tsSize := kRelSizeDelta * upDown;
{$IFC SubSuper}
IF fAllowSubSuper THEN
DoMenuCommand := DoMakeFullStyleCommand(newStyle, cSizeChange, addSize)
ELSE
{$ENDC}
DoMenuCommand := DoMakeStyleCommand(newStyle, cSizeChange, addSize);
END;
END;
PROCEDURE DoFontChange;
BEGIN
GetItem(GetMHandle(menu), item, aName);
GetFNum(aName, newStyle.tsFont);
DoMenuCommand := DoMakeStyleCommand(newStyle, cFontChange, doFont + doToggle);
END;
PROCEDURE DoJustChange;
VAR
newJust: INTEGER;
aJustChange: TJustCommand;
BEGIN
CASE aCmdNumber OF
cJustLeft:
newJust := teForceLeft;
cJustCenter:
newJust := teJustCenter;
cJustRight:
newJust := teJustRight;
END;
New(aJustChange);
FailNIL(aJustChange);
aJustChange.IJustCommand(SELF, newJust);
DoMenuCommand := aJustChange;
END;
PROCEDURE DoPlainChange;
BEGIN
{$IFC SubSuper}
IF fAllowSubSuper THEN
DoMenuCommand := DoSubSuperCommand(aCmdNumber)
ELSE
{$ENDC}
BEGIN
newStyle.tsFace := [];
DoMenuCommand := DoMakeStyleCommand(newStyle, cStyleChange, doFace);
END;
END;
PROCEDURE DoStyleChange;
BEGIN
WITH newStyle DO
CASE aCmdNumber OF
cBold:
tsFace := [bold];
cItalic:
tsFace := [italic];
cUnderline:
tsFace := [underline];
cOutline:
tsFace := [outline];
cShadow:
tsFace := [shadow];
cCondense:
tsFace := [condense];
cExtend:
tsFace := [extend];
END;
DoMenuCommand := DoMakeStyleCommand(newStyle, cStyleChange, doFace + doToggle);
END;
PROCEDURE DoSubSuperChange;
BEGIN
DoMenuCommand := DoSubSuperCommand(aCmdNumber);
END;
BEGIN { DoMenuCommand }
CmdToMenuItem(aCmdNumber, menu, item);
if ((menu = mFont) & fMenuFont) | ((menu = mSize) & fMenuSize) |
((menu = mStyle) & fMenuStyle) | ((menu = mJust) & fMenuJust) then
BEGIN
DoMenuCommand := gNoChanges;
IF menu = mFont THEN
DoFontChange
ELSE
CASE aCmdNumber OF
cSizeMin..cSizeMax:
DoSizeChange(cSizeBase);
cSizeNextUp:
DoRelSizeChange(kSizeNextUp);
cSizeNextDown:
DoRelSizeChange(kSizeNextDown);
cJustLeft..cJustRight:
DoJustChange;
cPlainText:
DoPlainChange;
cBold..cExtend:
DoStyleChange;
{$IFC SubSuper}
cSubscript..cSuperScript:
DoSubSuperChange;
{$ENDC}
OTHERWISE
DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
END;
END
else
DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoSetCursor(localPoint: Point; cursorRgn: RgnHandle): BOOLEAN; OVERRIDE;
VAR
myCursor: BOOLEAN;
qdExtent: Rect;
offset, lineHeight, fontAscent: INTEGER;
aStyle: TextStyle;
BEGIN
myCursor := FALSE;
IF SELF <> gClipView THEN
BEGIN
IF localPoint.v < 0 THEN { for IIfx bug in TEGetOffset }
offset := -1
ELSE
offset := TEGetOffset(localPoint, fHTE) - 1; { can use this directly, since we know we have styled TextEdit }
IF offset >= 0 THEN TEGetStyle(offset, aStyle, lineHeight, fontAscent, fHTE);
IF (offset >= 0) & (italic in aStyle.tsFace) THEN
SetCursor(GetCursor(kSlantBeam)^^)
ELSE
BEGIN
UseROMMap(TRUE);
SetCursor(GetCursor(iBeamCursor)^^);
END;
SetRect(qdExtent, localPoint.h, localPoint.v, { We could perhaps be more clever in }
localPoint.h, localPoint.v); { setting this region, but I really }
RectRgn(cursorRgn, qdExtent); { don't think it matters much. }
DoSetCursor := TRUE;
END
ELSE
DoSetCursor := FALSE;
END;
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$ENDC} {MenuAccess}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC SubSuper}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TEClose}
PROCEDURE TFullTEView.Free; OVERRIDE;
BEGIN
IF fAllowSubSuper THEN
Handle(fSubSuperHandle) := DisposeIfHandle(fSubSuperHandle);
INHERITED Free;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
{ Same as TTEView.DoKeyCommand, except FullTypingCommand instead of TypingCommand }
FUNCTION TFullTEView.OldDoKeyCommand(ch: Char; aKeyCode: INTEGER; VAR info: EventInfo): TCommand;
VAR
aTypingCommand: TFullTETypingCommand;
needNewCommand: BOOLEAN;
handledCharacter: BOOLEAN;
BEGIN
OldDoKeyCommand := gNoChanges;
handledCharacter := FALSE;
IF IsViewEnabled & fAcceptsChanges THEN
IF (ch >= ' ') | (ch = chReturn) | (ch = chBackspace) | (ch = chFwdDelete) THEN
BEGIN
IF Focus THEN; { Try to focus. }
IF (ch <> chBackspace) & (ch <> chFwdDelete) & { Check max size for text, and that we're
}
(fHTE^^.selStart = fHTE^^.selEnd) THEN { …not running out of memory }
IF ((fMaxChars - GetHandleSize(fText)) < 1) | MemSpaceIsLow THEN
BEGIN
gApplication.Beep(0);
EXIT(OldDoKeyCommand); { Flush further keystrokes }
END;
needNewCommand := (fFullTypingCommand = NIL);
IF NOT needNewCommand THEN
needNewCommand := fFullTypingCommand.fCompleted;
IF needNewCommand THEN
BEGIN
aTypingCommand := DoMakeFullTypingCommand(ch);
fFullTypingCommand := aTypingCommand;
OldDoKeyCommand := aTypingCommand;
END
ELSE
fFullTypingCommand.AddCharacter(ch);
handledCharacter := TRUE;
END
ELSE IF (ch >= chLeft) & (ch <= chDown) THEN
BEGIN
IF Focus THEN; { Try to focus. }
DoneTyping; { Like mousedown, further typing = new cmd }
fSpecsChanged := TRUE;
TEKey(ch, fHTE);
ScrollSelectionIntoView;
handledCharacter := TRUE;
END;
IF NOT handledCharacter THEN
{ Really want to call INHERITED INHERITED DoKeyCommand, but that's what }
{ will happen anyway ... }
OldDoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoMakeFullStyleCommand(aStyle: TextStyle; itsCmdNumber: CmdNumber;
itsMode: INTEGER): TFullTEStyleCommand;
{ This method is used rather than DoMakeStyleCommand only for font-size changes,
and only if fAllowSubSuper is TRUE }
VAR
aTEStyleCommand: TFullTEStyleCommand; { use "Full" class }
BEGIN
New(aTEStyleCommand);
FailNIL(aTEStyleCommand);
aTEStyleCommand.ITEStyleCommand(SELF, aStyle, itsCmdNumber, itsMode);
DoMakeFullStyleCommand := aTEStyleCommand;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoMakeFullTypingCommand(ch: Char): TFullTETypingCommand;
VAR
aTypingCommand: TFullTETypingCommand; { use "Full" class }
BEGIN
New(aTypingCommand);
FailNIL(aTypingCommand);
aTypingCommand.ITETypingCommand(SELF, ch);
DoMakeFullTypingCommand := aTypingCommand;
END;
{--------------------------------------------------------------------------------------------------}
{$S TENonRes}
PROCEDURE TFullTEView.DoneTyping; OVERRIDE;
BEGIN
IF fFullTypingCommand <> NIL THEN
fFullTypingCommand.CompleteTyping;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE SubSuperDrawGlue; EXTERNAL;
PROCEDURE OldDrawProc(previousDrawProc: ProcPtr; theStart, length: INTEGER;
theText: CharsPtr; theTEPtr: TEPtr; theTEHdl: TEHandle); EXTERNAL;
PROCEDURE TFullTEView.NewSubSuperHandle;
VAR aHandle: Handle;
theProcPtr: ProcPtr;
BEGIN
if fStyleType then
BEGIN
fAllowSubSuper := TRUE;
aHandle := NewPermHandle((2 * SizeOf(SubSuperElement)) + 4 + SizeOf(SubOrSuper) + SizeOf(ProcPtr));
FailNil(aHandle);
fSubSuperHandle := SubSuperHandle(aHandle);
WITH fSubSuperHandle^^ DO
BEGIN
nRuns := 1;
nullSubSuper := undefined;
nullBaseSize := 0;
runs[0].startChar := 0;
runs[0].subSuper := normal;
runs[0].baseSize := 0;
runs[1].startChar := fHTE^^.teLength + 1;
runs[1].subSuper := normal;
runs[1].baseSize := 0;
END;
theProcPtr := @SubSuperDrawGlue;
TECustomHook(intDrawHook, theProcPtr, fHTE);
fSubSuperHandle^^.previousDrawProc := theProcPtr;
END
{$IFC qDebug}
else
ProgramBreak('Trying to give SubSuper handle to non-styled TEView!')
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TENonRes}
PROCEDURE TFullTEView.StuffText(theText: Handle); OVERRIDE;
BEGIN
IF fHTE <> NIL THEN
BEGIN
INHERITED StuffText(theText);
IF fAllowSubSuper THEN
BEGIN
SetPermHandleSize(Handle(fSubSuperHandle), (2 * SizeOf(SubSuperElement)) + 4 + SizeOf(SubOrSuper) + SizeOf(ProcPtr));
WITH fSubSuperHandle^^ DO
BEGIN
nRuns := 1;
nullSubSuper := undefined;
nullBaseSize := 0;
runs[0].startChar := 0;
runs[0].subSuper := normal;
runs[0].baseSize := 0;
runs[1].startChar := fHTE^^.teLength + 1;
runs[1].subSuper := normal;
runs[1].baseSize := 0;
END;
END;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S TENonRes}
PROCEDURE TFullTEView.StuffSubSuper(theSubSuperHandle: SubSuperHandle; redraw: BOOLEAN);
VAR
oldNullSubSuper: SubOrSuper;
oldNullBaseSize: INTEGER;
BEGIN
IF fAllowSubSuper & (fHTE <> NIL) THEN
BEGIN
WITH fSubSuperHandle^^ DO
BEGIN
oldNullSubSuper := nullSubSuper;
oldNullBaseSize := nullBaseSize;
END;
SetSubSuper(0, MAXINT, theSubSuperHandle, redraw);
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := oldNullSubSuper;
nullBaseSize := oldNullBaseSize;
END;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE NewDrawProc(theStart, length: INTEGER; theText: CharsPtr; theTEPtr: TEPtr; theTEHdl: TEHandle);
VAR theSubSuper: SubSuperHandle;
theStyleHandle: TEStyleHandle;
theEnd, thru, i: INTEGER;
changeBase: BOOLEAN;
theFontInfo: FontInfo;
shiftAmount: INTEGER;
offset: INTEGER;
halfSize: INTEGER;
BEGIN
theStyleHandle := GetStylHandle(theTEHdl);
FailNil(theStyleHandle);
theSubSuper := SubSuperHandle(TFullTEView(theStyleHandle^^.teRefCon).fSubSuperHandle);
FailNil(theSubSuper);
offset := ORD(theText) - ORD(theTEHdl^^.hText^);
theEnd := theStart + length;
i := GetIndex(theSubSuper, theStart + offset);
MoveHHi(Handle(theSubSuper));
HLock(Handle(theSubSuper));
WITH theSubSuper^^ DO
REPEAT
thru := MIN(theEnd + offset, runs[i + 1].startChar);
changeBase := runs[i].subSuper <> normal;
if changeBase then
BEGIN
halfSize := thePort^.txSize;
TextSize(runs[i].baseSize);
GetFontInfo(theFontInfo);
TextSize(halfSize);
if runs[i].subSuper = subscript then
shiftAmount := theFontInfo.descent
else
BEGIN
shiftAmount := theFontInfo.ascent;
GetFontInfo(theFontInfo);
shiftAmount := theFontInfo.ascent - shiftAmount;
END;
Move(0, shiftAmount);
END;
OldDrawProc(previousDrawProc, theStart, thru - offset - theStart, theText, theTEPtr, theTEHdl);
if changeBase then
Move(0, -shiftAmount);
i := i + 1;
theStart := thru - offset;
UNTIL theStart >= theEnd;
HUnlock(Handle(theSubSuper));
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.GetSubSuperHandle: SubSuperHandle;
VAR i, runCount, firstRun, lastRun: INTEGER;
startOfSelection, endOfSelection: INTEGER;
me: SubSuperHandle;
BEGIN
WITH fHTE^^,fSubSuperHandle^^ DO
BEGIN
startOfSelection := MAX(selStart, 0);
endOfSelection := MIN(selEnd, runs[nRuns].startChar - 1);
END;
WITH fSubSuperHandle^^ DO
if (startOfSelection < endOfSelection) | (nullSubSuper = undefined) then
BEGIN
firstRun := 0;
WHILE runs[firstRun].startChar < startOfSelection DO
firstRun := firstRun + 1;
if runs[firstRun].startChar > startOfSelection then
firstRun := firstRun - 1;
lastRun := firstRun + 1;
WHILE runs[lastRun].startChar < endOfSelection DO
lastRun := lastRun + 1;
runCount := lastRun - firstRun + 1;
END
else
runCount := 2;
me := SubSuperHandle(NewPermHandle((runCount * SizeOf(SubSuperElement)) + 4 + SizeOf(SubOrSuper) + SizeOf(ProcPtr)));
FailNil(me);
WITH me^^ DO
BEGIN
nRuns := runCount - 1;
nullSubSuper := undefined;
nullBaseSize := 0;
runs[0].startChar := 0;
if (startOfSelection < endOfSelection) | (fSubSuperHandle^^.nullSubSuper = undefined) then
BEGIN
if firstRun = fSubSuperHandle^^.nRuns then firstRun := firstRun - 1;
runs[0].subSuper := fSubSuperHandle^^.runs[firstRun].subSuper;
runs[0].baseSize := fSubSuperHandle^^.runs[firstRun].baseSize;
FOR i := 1 TO runCount - 2 DO
BEGIN
runs[i].startChar :=
fSubSuperHandle^^.runs[firstRun + i].startChar - startOfSelection;
runs[i].subSuper := fSubSuperHandle^^.runs[firstRun + i].subSuper;
runs[i].baseSize := fSubSuperHandle^^.runs[firstRun + i].baseSize;
END;
END
else
BEGIN
runs[0].subSuper := fSubSuperHandle^^.nullSubSuper;
runs[0].baseSize := fSubSuperHandle^^.nullBaseSize;
END;
WITH runs[runCount - 1] DO
BEGIN
startChar := endOfSelection - startOfSelection + 1;
subSuper := normal;
baseSize := 0;
END;
END;
GetSubSuperHandle := me;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.DeleteSubSuperElement(index: INTEGER);
VAR newLength: LONGINT;
BEGIN
WITH fSubSuperHandle^^ DO
BEGIN
FOR index := index TO nRuns - 1 DO
runs[index] := runs[index + 1];
nRuns := nRuns - 1;
newLength := ((nRuns + 1) * SizeOf(SubSuperElement)) + 4 + SizeOf(SubOrSuper) + SizeOf(ProcPtr);
END;
SetPermHandleSize(Handle(fSubSuperHandle), newLength);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.DeleteSubSuperChars(theStart, theEnd: INTEGER);
VAR
i, j, firstRun: INTEGER;
test: BOOLEAN;
theSubSuper: SubOrSuper;
BEGIN
{ First, modify the offsets appropriately: }
WITH fSubSuperHandle^^ DO
BEGIN
theStart := MAX(theStart, 0);
theEnd := MIN(theEnd, runs[nRuns].startChar - 1);
IF theStart >= theEnd THEN EXIT(DeleteSubSuperChars);
IF NOT gNoScripts THEN
BEGIN
{ Adjust for multi-byte characters... }
WHILE CharByte(fText^, theStart) > 0 DO
theStart := theStart - 1;
i := CharByte(fText^, theEnd - 1);
WHILE (i <> 0) & (i <> 1) DO
BEGIN
theEnd := theEnd + 1;
i := CharByte(fText^, theEnd - 1);
END;
END;
firstRun := 0;
WHILE runs[firstRun + 1].startChar <= theStart DO
firstRun := firstRun + 1;
i := firstRun + 1;
WHILE runs[i].startChar < theEnd DO
BEGIN
runs[i].startChar := theEnd;
i := i + 1;
END;
FOR i := firstRun + 1 TO nRuns DO
WITH runs[i] DO
startChar := startChar - (theEnd - theStart);
nullSubSuper := runs[firstRun].subSuper;
nullBaseSize := runs[firstRun].baseSize;
END;
{ Second, clean up the results as necessary: }
i := firstRun;
WHILE (i < fSubSuperHandle^^.nRuns) & (fSubSuperHandle^^.nRuns > 1) DO
WITH fSubSuperHandle^^ DO
BEGIN
j := runs[i + 1].startChar;
IF i = (nRuns - 1) THEN j := j - 1;
IF runs[i].startChar >= j THEN
DeleteSubSuperElement(i)
ELSE IF (i > 0) & (runs[i].subSuper = runs[i - 1].subSuper) THEN
BEGIN
runs[i - 1].baseSize := MAX(runs[i - 1].baseSize, runs[i].baseSize);
DeleteSubSuperElement(i);
END
ELSE
i := i + 1;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.InsertSubSuperChars(insertionPoint, length: INTEGER; theSubSuperHandle: SubSuperHandle);
VAR i: INTEGER;
BEGIN
{ First, modify the offsets appropriately: }
WITH fSubSuperHandle^^ DO
BEGIN
insertionPoint := MIN(insertionPoint, runs[nRuns].startChar - 1);
i := 1;
WHILE runs[i].startChar < insertionPoint DO
i := i + 1;
if runs[i].startChar = insertionPoint then i := i + 1;
FOR i := i TO nRuns DO
WITH runs[i] DO
startChar := startChar + length;
END;
{ And now: }
SetSubSuper(insertionPoint, insertionPoint + length, theSubSuperHandle, kDontRedraw);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.ContinuousSubSuper(theStart, theEnd: INTEGER; VAR which: SubOrSuper; VAR theBaseSize: INTEGER): BOOLEAN;
VAR i: INTEGER;
BEGIN
if fSubSuperHandle = NIL then
BEGIN
ContinuousSubSuper := TRUE;
which := normal;
theBaseSize := -1; {ie, undefined}
END
else if (theStart >= theEnd) & (fSubSuperHandle^^.nullSubSuper <> undefined) then
BEGIN
ContinuousSubSuper := TRUE;
which := fSubSuperHandle^^.nullSubSuper;
theBaseSize := fSubSuperHandle^^.nullBaseSize;
END
else
BEGIN
WITH fSubSuperHandle^^ DO
BEGIN
i := 0;
WHILE runs[i].startChar < theStart DO
i := i + 1;
if (theStart >= theEnd) | (runs[i].startChar > theStart) then
i := MAX(i - 1, 0);
if runs[i + 1].startChar >= theEnd then
BEGIN
ContinuousSubSuper := TRUE;
which := runs[i].subSuper;
theBaseSize := runs[i].baseSize;
END
else
ContinuousSubSuper := FALSE;
END;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.GetSubSuper(theStart: INTEGER; VAR theSubSuper: SubOrSuper; theBaseSize: INTEGER);
BEGIN
WITH fSubSuperHandle^^.runs[GetIndex(fSubSuperHandle, theStart)] DO
BEGIN
theSubSuper := subSuper;
theBaseSize := baseSize;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEView.SetSubSuper(theStart, theEnd: INTEGER; theSubSuperHandle: SubSuperHandle; redraw: BOOLEAN);
VAR i, j: INTEGER;
aSubSuper: SubOrSuper;
PROCEDURE SetOneSubSuper(theStart, theEnd: INTEGER; which: SubOrSuper; theBaseSize: INTEGER);
VAR theStyleHandle: TEStyleHandle;
i: INTEGER;
prevSubSuper: SubOrSuper;
prevBaseSize: INTEGER;
PROCEDURE InsertElement(index, theStart: INTEGER; which: SubOrSuper; theBaseSize: INTEGER);
VAR
newLength: LONGINT;
i: INTEGER;
BEGIN
newLength := ((fSubSuperHandle^^.nRuns + 2) * SizeOf(SubSuperElement)) + 4 + SizeOf(SubOrSuper) + SizeOf(ProcPtr);
SetPermHandleSize(Handle(fSubSuperHandle), newLength);
WITH fSubSuperHandle^^ DO
BEGIN
nRuns := nRuns + 1;
FOR i := nRuns DOWNTO index + 1 DO { ¿should do one BlockMove instead .... }
runs[i] := runs[i - 1];
runs[index].startChar := theStart;
runs[index].subSuper := which;
runs[index].baseSize := theBaseSize;
END;
END;
BEGIN {SetOneSubSuper}
i := 0;
WITH fSubSuperHandle^^ DO
WHILE runs[i].startChar < theStart DO
i := i + 1;
if fSubSuperHandle^^.runs[i].startChar = theStart then
WITH fSubSuperHandle^^.runs[i] DO
BEGIN
prevSubSuper := subSuper;
subSuper := which;
prevBaseSize := baseSize;
baseSize := theBaseSize;
i := i + 1;
END
else
BEGIN
WITH fSubSuperHandle^^.runs[i - 1] DO
BEGIN
prevSubSuper := subSuper;
prevBaseSize := baseSize;
END;
if prevSubSuper <> which then
BEGIN
InsertElement(i, theStart, which, theBaseSize);
i := i + 1;
END;
END;
WHILE fSubSuperHandle^^.runs[i].startChar < theEnd DO
BEGIN
WITH fSubSuperHandle^^.runs[i] DO
BEGIN
prevSubSuper := subSuper;
prevBaseSize := MAX(baseSize, prevBaseSize);
END;
DeleteSubSuperElement(i);
END;
WITH fSubSuperHandle^^ DO
if (runs[i].startChar > theEnd) & (theEnd < runs[nRuns].startChar - 1) then
if prevSubSuper <> which then
BEGIN
InsertElement(i, theEnd, prevSubSuper, prevBaseSize);
i := i + 1;
END;
i := 1;
WHILE i < fSubSuperHandle^^.nRuns DO
WITH fSubSuperHandle^^ DO
if runs[i].subSuper = runs[i - 1].subSuper then
BEGIN
runs[i - 1].baseSize := MAX(runs[i - 1].baseSize, runs[i].baseSize);
DeleteSubSuperElement(i);
END
else
i := i + 1;
END; {SetOneSubSuper}
BEGIN {SetSubSuper}
{$IFC qDebug}
if fSubSuperHandle = NIL then
ProgramBreak('fSubSuperHandle is NIL!');
{$ENDC}
theStart := MAX(theStart, 0);
WITH fSubSuperHandle^^ DO
theEnd := MIN(theEnd, runs[nRuns].startChar - 1);
IF theSubSuperHandle = NIL THEN
if fSubSuperHandle^^.nullSubSuper <> undefined then
BEGIN
WITH fSubSuperHandle^^ DO
SetOneSubSuper(theStart, theEnd, nullSubSuper, nullBaseSize);
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := undefined;
nullBaseSize := 0;
END
END
else
WITH fSubSuperHandle^^.runs[GetIndex(fSubSuperHandle, theStart - 1)] DO
SetOneSubSuper(theStart, theEnd, subSuper, baseSize)
ELSE
if theStart >= theEnd then
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := theSubSuperHandle^^.runs[0].subSuper;
nullBaseSize := theSubSuperHandle^^.runs[0].baseSize;
END
else
BEGIN
MoveHHi(Handle(theSubSuperHandle));
HLock(Handle(theSubSuperHandle));
WITH theSubSuperHandle^^ DO
FOR i := 0 TO nRuns - 1 DO
BEGIN
j := runs[i + 1].startChar;
IF i = nRuns - 1 THEN j := j - 1;
SetOneSubSuper(theStart + runs[i].startChar,
theStart + j,
runs[i].subSuper, runs[i].baseSize);
END;
HUnlock(Handle(theSubSuperHandle));
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := undefined;
nullBaseSize := 0
END
END;
if redraw then ForceRedraw;
fSpecsChanged := TRUE;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEView.DoSubSuperCommand(aCmdNumber: CmdNumber): TTECommand;
VAR
aSubSuperCommand: TFullTESubSuperCommand;
BEGIN
New(aSubSuperCommand);
FailNIL(aSubSuperCommand);
aSubSuperCommand.ITFullTESubSuperCommand(SELF, aCmdNumber);
DoSubSuperCommand := aSubSuperCommand;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEClipboard}
FUNCTION TFullTEView.GivePasteData(aDataHandle: Handle; dataType: ResType): LONGINT; OVERRIDE;
VAR
oldStart: INTEGER;
oldEnd: INTEGER;
aSize: LONGINT;
aHandle: Handle;
err: OSErr;
savedPerm: BOOLEAN;
fi: FailInfo;
PROCEDURE HdlGivePasteFailed(error: OSErr; message: LONGINT);
BEGIN
DisposIfHandle(aHandle);
END;
BEGIN
IF dataType <> kSubSuperClipType THEN
GivePasteData := INHERITED GivePasteData(aDataHandle, dataType)
ELSE
BEGIN
aSize := 0;
savedPerm := FALSE;
aHandle := NIL;
CatchFailures(fi, HdlGivePasteFailed);
IF fAllowSubSuper THEN
BEGIN
WITH fHTE^^ DO
BEGIN
oldStart := selStart;
oldEnd := selEnd;
END;
SetSelect(0, MAXINT, fHTE);
aHandle := Handle(GetSubSuperHandle);
SetSelect(oldStart, oldEnd, fHTE);
IF aHandle <> NIL THEN
BEGIN
aSize := GetHandleSize(aHandle);
IF aDataHandle <> NIL THEN
BEGIN
savedPerm := PermAllocation(TRUE);
MoveHHi(aHandle); { Try to prevent fragmentation, in case }
HLock(aHandle); { Can't move while we're copying it! }
err := PtrToXHand(aHandle^, { Copy styles into user-supplied handle }
aDataHandle, aSize);
HUnlock(aHandle); { Okay for it to move again }
savedPerm := PermAllocation(savedPerm);
IF err <> noErr THEN
Failure(phStylesTooBig, phStylesTooBig + msgAlert);
END;
DisposIfHandle(aHandle);
END
ELSE IF aDataHandle <> NIL THEN
Failure(phStylesTooBig, phStylesTooBig + msgAlert);
END;
FailSpaceIsLow;
Success(fi);
GivePasteData := aSize;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S TENonRes}
PROCEDURE TFullTEView.WriteToDeskScrap; OVERRIDE;
BEGIN
INHERITED WriteToDeskScrap;
IF fAllowSubSuper THEN
FailOSErr(PutDeskScrapData(kSubSuperClipType, Handle(fSubSuperHandle)));
END;
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$ENDC} {SubSuper}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTEView.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TFullTEView', NIL, bClass);
DoToField('fSelAnchor', @fSelAnchor, bInteger);
DoToField('fUpDown', @fUpDown, bBoolean);
DoToField('fUpDownH', @fUpDownH, bInteger);
DoToField('fDoubleAnchor', @fDoubleAnchor, bInteger);
DoToField('fDoubleStart', @fDoubleStart, bInteger);
DoToField('fDoubleEnd', @fDoubleEnd, bInteger);
{$IFC MenuAccess}
DoToField('fMenuFont', @fMenuFont, bBoolean);
DoToField('fMenuSize', @fMenuSize, bBoolean);
DoToField('fMenuStyle', @fMenuStyle, bBoolean);
DoToField('fMenuJust', @fMenuJust, bBoolean);
DoToField('fMenuUpDown', @fMenuUpDown, bBoolean);
DoToField('fAllowedStyles', @fAllowedStyles, bInteger);
{$ENDC}
{$IFC SubSuper}
DoToField('fFullTypingCommand', @fFullTypingCommand, bObject);
DoToField('fAllowSubSuper', @fAllowSubSuper, bBoolean);
DoToField('fSubSuperHandle', @fSubSuperHandle, bHandle);
{$ENDC}
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC SubSuper}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TEOpen}
PROCEDURE TFullSubSuperTEView.ITEView(itsDocument: TDocument; itsSuperView: TView; itsLocation, itsSize: VPoint;
itsHDeterminer, itsVDeterminer: SizeDeterminer; itsInset: Rect;
itsTextStyle: TextStyle; itsJustification: INTEGER; itsStyleType,
itsAutoWrap: BOOLEAN); OVERRIDE;
BEGIN
INHERITED ITEView(itsDocument, itsSuperView, itsLocation, itsSize,
itsHDeterminer, itsVDeterminer, itsInset, itsTextStyle,
itsJustification, itsStyleType, itsAutoWrap);
if fStyleType then NewSubSuperHandle;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEOpen}
PROCEDURE TFullSubSuperTEView.IRes(itsDocument: TDocument; itsSuperView: TView; VAR itsParams: Ptr); OVERRIDE;
BEGIN
INHERITED IRes(itsDocument, itsSuperView, itsParams);
NewSubSuperHandle;
END;
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$ENDC} {SubSuper}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TEOpen}
PROCEDURE TFullTEMouseCommand.ITEMouseCommand(itsTEView: TFullTEView; shift: BOOLEAN);
VAR nonAnchor: INTEGER;
BEGIN
ICommand(cTextCommand, NIL, itsTEView, itsTEView.GetScroller(TRUE));
fCanUndo := FALSE;
fCausesChange := FALSE;
fTEView := itsTEView;
fShift := shift;
fWordSelect := FALSE;
fSelAnchor := itsTEView.fSelAnchor;
fNewAnchor := fSelAnchor;
WITH itsTEView.fHTE^^ DO
BEGIN
fOrigStart := selStart;
fOrigEnd := selEnd;
END;
{$IFC SubSuper}
WITH itsTEView DO
if fAllowSubSuper then
WITH fSubSuperHandle^^ DO
BEGIN
nullSubSuper := undefined;
nullBaseSize := 0;
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTEMouseCommand.TrackFeedback(anchorPoint, nextPoint: VPoint;
turnItOn, mouseDidMove: BOOLEAN); OVERRIDE;
BEGIN
{ default behavior would have drawn a gray rectangle }
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION TFullTEMouseCommand.TrackMouse(aTrackPhase: TrackPhase;
VAR anchorPoint, previousPoint, nextPoint: VPoint;
mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
VAR
msePos, newStart, newEnd: INTEGER;
PROCEDURE ResetAnchor;
BEGIN
if fSelAnchor < 0 then {previous double-click}
if newStart = fOrigStart then
fNewAnchor := fOrigStart
else
fNewAnchor := fOrigEnd
END;
BEGIN
if aTrackPhase = trackRelease then
BEGIN
fTEView.fSelAnchor := fNewAnchor;
TrackMouse := gNoChanges;
END
else
BEGIN
TrackMouse := SELF;
if ClickLoopForTTEView then;
msePos := fTEView.PtToOffset(nextPoint);
if aTrackPhase = trackPress then
BEGIN
if gClickCount = 1 then
BEGIN
WITH fTEView DO {save current info in case this}
BEGIN {turns out to be a double-click}
fDoubleAnchor := fSelAnchor;
fDoubleStart := fOrigStart;
fDoubleEnd := fOrigEnd;
END;
if fShift then
BEGIN
newStart := MIN(msePos, fOrigStart);
newEnd := MAX(msePos, fOrigEnd);
ResetAnchor;
END
else
BEGIN
newStart := msePos;
newEnd := msePos;
fOrigStart := msePos;
fOrigEnd := msePos;
fNewAnchor := msePos;
END
END
else if gClickCount >= 2 then
BEGIN
WITH fTEView DO {restore saved info}
BEGIN
fSelAnchor := fDoubleAnchor;
fNewAnchor := fSelAnchor;
fOrigStart := fDoubleStart;
fOrigEnd := fDoubleEnd;
END;
fWordSelect := TRUE;
if gClickCount = 2 then
BEGIN
if NOT fTEView.WordBounds(msePos, newStart, newEnd) then
if fTEView.WordBounds(msePos-1, newStart, newEnd) then;
END
else
BEGIN
if NOT fTEView.TripleBounds(msePos, newStart, newEnd) then
if fTEView.TripleBounds(msePos-1, newStart, newEnd) then;
END;
newEnd := newEnd + 1;
if fShift then
BEGIN
newStart := MIN(newStart, fOrigStart);
newEnd := MAX(newEnd, fOrigEnd);
ResetAnchor;
END
else
BEGIN
fOrigStart := newStart;
fOrigEnd := newEnd;
fSelAnchor := -1;
fNewAnchor := -1;
END
END
END
else {trackMove}
BEGIN
if fWordSelect then
BEGIN
if gClickCount = 2 then
BEGIN
if NOT fTEView.WordBounds(msePos, newStart, newEnd) then
if fTEView.WordBounds(msePos-1, newStart, newEnd) then;
END
else
BEGIN
if NOT fTEView.TripleBounds(msePos, newStart, newEnd) then
if fTEView.TripleBounds(msePos-1, newStart, newEnd) then;
END;
newEnd := newEnd + 1;
if fShift then
if newEnd >= fOrigEnd then
BEGIN
newStart := fOrigStart;
newEnd := MAX(newEnd, fOrigEnd);
END
else
BEGIN
newStart := MIN(newStart, fOrigStart);
newEnd := fOrigEnd;
END
else
BEGIN
newStart := MIN(newStart, fOrigStart);
newEnd := MAX(newEnd, fOrigEnd);
ResetAnchor;
END
END
else
BEGIN
newStart := MIN(msePos, fOrigStart);
newEnd := MAX(msePos, fOrigEnd);
if fShift then ResetAnchor;
END;
END;
fTEView.DrawSelection(newStart, newEnd);
END;
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTEMouseCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TFullTEMouseCommand', NIL, bClass);
DoToField('fTEView', @fTEView, bObject);
DoToField('fShift', @fShift, bBoolean);
DoToField('fWordSelect',@fWordSelect, bBoolean);
DoToField('fSelAnchor', @fSelAnchor, bInteger);
DoToField('fNewAnchor', @fNewAnchor, bInteger);
DoToField('fOrigStart', @fOrigStart, bInteger);
DoToField('fOrigEnd', @fOrigEnd, bInteger);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
FUNCTION IsBlank(pText: Ptr; offset: Integer; VAR length: Integer): BOOLEAN;
VAR
i: Integer;
BEGIN
if gNoScripts then
BEGIN
IsBlank := CHAR(PTR(Ord4(pText) + offset)^) = ' ';
length := 1;
END
else
BEGIN
i := CharType(pText, offset);
IsBlank := BAND(i, $0F00) = smPunctBlank;
if CharByte(pText, offset) = 0 then
length := 1
else
length := 2;
END
END;
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
PROCEDURE TFullTECommand.ITECommand(itsTEView: TTEView; itsCmdNumber: CmdNumber; itsSaveText: BOOLEAN); OVERRIDE;
VAR
origStart, origEnd, lWordStart, lWordEnd,
rWordStart, rWordEnd: Integer;
spaceLeft, spaceRight: Boolean;
i: Integer;
{$IFC SubSuper}
fi: FailInfo;
PROCEDURE HdlInitFailed(error: OSErr; message: LONGINT);
BEGIN
Free;
END;
{$ENDC}
BEGIN
{ ********************* implement intelligent Cut/Clear/Copy ***************** }
if (itsCmdNumber = cCut) | (itsCmdNumber = cClear) | (itsCmdNumber = cCopy) then
WITH itsTEView.fHTE^^ DO
BEGIN
gFullWordLeft := FALSE;
gFullWordRight := FALSE;
origStart := selStart;
origEnd := selEnd;
if origStart < origEnd then
BEGIN
if TFullTEView(itsTEView).WordBounds(origStart, lWordStart, lWordEnd)
& (lWordStart = origStart) & (lWordEnd < origEnd) then
BEGIN
gFullWordLeft := TRUE;
spaceLeft := (lWordStart > 0) & IsBlank(hText^, lWordStart-1, i);
END
else
spaceLeft := FALSE;
if TFullTEView(itsTEView).WordBounds(origEnd - 1, rWordStart, rWordEnd)
& (rWordStart >= origStart) & (rWordEnd = origEnd - 1) then
BEGIN
gFullWordRight := TRUE;
rWordEnd := rWordEnd + 1;
spaceRight := (rWordEnd < teLength) & IsBlank(hText^, rWordEnd, i);
END
else
spaceRight := FALSE;
if itsCmdNumber <> cCopy then
if spaceLeft &
(gFullWordRight | (origEnd >= teLength) |
IsBlank(hText^, origEnd, i)) then
selStart := selStart - 1
else if spaceRight &
(gFullWordLeft | (origStart <= 0) |
IsBlank(hText^, origStart-1, i)) then
selEnd := selEnd + 1;
END;
END;
{$IFC SubSuper}
fOldSubSuper := NIL;
fNewSubSuper := NIL;
{$ENDC}
INHERITED ITECommand(itsTEView, itsCmdNumber, itsSaveText);
{$IFC SubSuper}
IF TFullTEView(itsTEView).fAllowSubSuper THEN
BEGIN
CatchFailures(fi, HdlInitFailed);
fOldSubSuper := TFullTEView(itsTEView).GetSubSuperHandle;
FailNIL(fOldSubSuper);
Success(fi);
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$IFC SubSuper}
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECommand.BanishOldText; OVERRIDE;
BEGIN
IF TFullTEView(fTEView).fAllowSubSuper & (fOldEnd > fOldStart) THEN
TFullTEView(fTEView).DeleteSubSuperChars(fOldStart, fOldEnd);
INHERITED BanishOldText;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECommand.Free; OVERRIDE;
BEGIN
DisposIfHandle(fOldSubSuper);
DisposIfHandle(fNewSubSuper);
INHERITED Free;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECommand.InstallNewText; OVERRIDE;
BEGIN
IF fNewEnd > fNewStart THEN
BEGIN
if TFullTEView(fTEView).fAllowSubSuper then
TFullTEView(fTEView).InsertSubSuperChars(fOldStart, fNewEnd - fNewStart, fNewSubSuper);
INHERITED InstallNewText;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECommand.RemoveAdditions; OVERRIDE;
BEGIN
IF TFullTEView(fTEView).fAllowSubSuper & (fNewText <> NIL) THEN
TFullTEView(fTEView).DeleteSubSuperChars(fNewStart, fNewEnd);
INHERITED RemoveAdditions;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECommand.ReviveDeletions; OVERRIDE;
VAR i, position, length: INTEGER;
BEGIN
if TFullTEView(fTEView).fAllowSubSuper & (GetHandleSize(fOldText) > 0) then
TFullTEView(fTEView).InsertSubSuperChars(fOldStart, fOldEnd - fOldStart, fOldSubSuper);
INHERITED ReviveDeletions;
END;
{--------------------------------------------------------------------------------------------------}
{$ENDC} {SubSuper}
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTECommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TFullTECommand', NIL, bClass);
{$IFC SubSuper}
DoToField('fOldSubSuper', @fOldSubSuper, bHandle);
DoToField('fNewSubSuper', @fNewSubSuper, bHandle);
{$ENDC}
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
PROCEDURE TFullTECutCopyCommand.ITECutCopyCommand(itsTEView: TTEView; itsCmdNumber: CmdNumber);
{no change from TTECutCopyCommand}
BEGIN
fClipCreated := FALSE;
ITECommand(itsTEView, itsCmdNumber, TRUE);
fChangesClipboard := TRUE;
fCausesChange := itsCmdNumber <> cCopy;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECutCopyCommand.Free; OVERRIDE;
{change from TTECutCopyCommand for sub/superscripts}
BEGIN
IF fClipCreated THEN
BEGIN
fOldText := NIL;
{$IFC SubSuper}
fOldSubSuper := NIL;
{$ENDC}
END;
INHERITED Free;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECutCopyCommand.DoIt; OVERRIDE;
{changes from TTECutCopyCommand to handle sub/superscripts}
VAR
{$IFC SubSuper}
clipTEView: TFullSubSuperTEView;
{$ELSEC}
clipTEView: TTEView;
{$ENDC}
clipHere: BOOLEAN;
fi: FailInfo;
clipStyle: TextStyle;
itsSize: VPoint;
itsMargins: Rect;
PROCEDURE HdlClipFailed(error: OSErr; message: LONGINT);
BEGIN
FreeIfObject(clipTEView);
clipTEView := NIL;
END;
BEGIN {TTECutCopyCommand.DoIt}
IF fTEView.Focus THEN; {??? What if Focus fails}
SetTextStyle(clipStyle, applFont, [], { Initial style same as virgin TEView }
12, gRGBBlack);
SetVPt(itsSize, 100, 50); { An arbitrary initial size. }
SetRect(itsMargins, 10, 8, 10, 0); { No bottom margin. }
New(clipTEView); { Create a new view for the clipboard }
FailNIL(clipTEView);
WITH fTEView DO
clipTEView.ITEView(NIL, NIL, { Initialize view }
gZeroVPt, itsSize, sizeSuperView, sizeVariable, itsMargins, clipStyle,
teJustLeft, fStyleType, fAutoWrap);
clipTEView.fAcceptsChanges := FALSE; { This is a read-only view }
CatchFailures(fi, HdlClipFailed); { Cut can eat into temp memory so users can
}
{ …rescue text from overweight documents }
IF NOT fCausesChange THEN { If Copy-ing, assure there's enough room }
FailSpaceIsLow;
Success(fi);
clipTEView.StuffText(fOldText);
FailSpaceIsLow;
{??? GOT TO FIGURE OUT SOME WAY TO PRE-FLIGHT THIS! ??????????????????????????????????? }
IF clipTEView.fStyleType = kWithStyle THEN { If record has style }
SetStylScrap(0, MAXINT, fOldStyles, { …then put in the styles }
FALSE, clipTEView.fHTE);
FailSpaceIsLow;
{$IFC SubSuper}
WITH TFullTEView(fTEView) DO
IF fAllowSubSuper THEN { If record has sub/superscripts }
clipTEView.SetSubSuper(0, MAXINT, fOldSubSuper, kDontRedraw);
FailSpaceIsLow;
{$ENDC}
clipTEView.fFreeText := TRUE; { Let TEView know it has to free the text }
gApplication.ClaimClipboard(clipTEView); { Okay to claim (will call RecalcText!) }
fClipCreated := TRUE; { We be done }
DoMainFunction; { Do the actual cut/copy }
{$IFC qDebug}
IF pTEIntenseDebugging THEN
BEGIN
DumpTERecord(clipTEView.fHTE);
DumpTTECommand(SELF);
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTECutCopyCommand.ReviveDeletions; OVERRIDE;
{no change from TTECutCopyCommand}
BEGIN
IF fCmdNumber = cCut THEN
INHERITED ReviveDeletions; { Don't do it for COPY }
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTECutCopyCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
{no change from TTECutCopyCommand}
BEGIN
DoToField('TFullTECutCopyCommand', NIL, bClass);
DoToField('fClipCreated', @fClipCreated, bBoolean);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
PROCEDURE TFullTEPasteCommand.ITEPasteCommand(itsTEView: TFullTEView);
{ **** section added for intelligent paste **** }
{ & other changes for sub/superscript handling }
{ We can't use TEPaste because it clobbers the DeskScrap; the text would be recoverable
from the special TextEdit Scrap, but other types of non-TEXT scrap are permanently
lost, it seems }
VAR
savedPerm: BOOLEAN;
newLength: INTEGER;
newStyleLen: LONGINT;
newText: Handle;
newStyles: StScrpHandle;
{$IFC SubSuper}
newSubSuperLen: LONGINT;
newSubSuper: SubSuperHandle;
{$ENDC}
dataType: ResType;
fi: FailInfo;
space: STRING[1];
long: LONGINT;
i, j: INTEGER;
addLeft, delLeft,
addRight, delRight: INTEGER;
PROCEDURE HdlPasteFailed(error: OSErr; message: LONGINT);
BEGIN
IF newText <> fNewText THEN { newText is assigned to fNewText }
newText := DisposeIfHandle(newText); { …so avoid disposing twice. }
IF newStyles <> fNewStyles THEN { Ditto for newStyles. }
Handle(newStyles) := DisposeIfHandle(newStyles);
{$IFC SubSuper}
IF newSubSuper <> fNewSubSuper THEN { and for newSubSuperHandle. }
Handle(newSubSuper) := DisposeIfHandle(newSubSuper);
{$ENDC}
Free;
END;
BEGIN
ITECommand(itsTEView, cPaste, TRUE); { Perform stock initializations }
savedPerm := FALSE;
newStyleLen := 0; { Assume there are no new styles }
newStyles := NIL;
newText := NIL;
{$IFC SubSuper}
newSubSuperLen := 0;
newSubSuper := NIL; { Ditto for sub/super }
{$ENDC}
CatchFailures(fi, HdlPasteFailed);
newText := NewPermHandle(0); { Create handle to receive clipboard data }
FailNIL(newText);
IF itsTEView.fStyleType = kWithStyle THEN
BEGIN
newStyles := StScrpHandle(NewPermHandle(0)); { Same for handle to receive style info }
FailNIL(newStyles);
END;
{$IFC SubSuper}
IF itsTEView.fAllowSubSuper THEN
BEGIN
newSubSuper := SubSuperHandle(NewPermHandle(0)); { Same for handle to receive sub/super info }
FailNil(newSubSuper);
END;
{$ENDC}
newLength := gApplication.GetDataToPaste(newText, dataType);
{ **************************** intelligent paste: **************************** }
if newLength > 0 then
{$IFC qDebug}
IF dataType <> 'TEXT' THEN
ProgramBreak('TEPasteCommandNew given some non-text from clipboard')
ELSE
{$ENDC}
BEGIN
addLeft := 0;
delLeft := 0;
addRight := 0;
delRight := 0;
space := ' ';
if gFullWordLeft then
if TFullTEView(fTEView).WordBounds(fHTE^^.selStart-1, i, j) then
BEGIN
if NOT IsBlank(newText^, 0, i) then
BEGIN
addLeft := 1;
long := Munger(newText, 0, NIL,0, @space[1],1);
FailMemError;
newLength := newLength + 1;
END;
END
else
if IsBlank(newText^, 0, i) then
BEGIN
delLeft := i;
long := Munger(newText, 0, NIL,i, @space[1],0);
FailMemError;
newLength := newLength - i;
END;
if gFullWordRight then
if TFullTEView(fTEView).WordBounds(fHTE^^.selEnd, i, j) then
BEGIN
if NOT IsBlank(newText^, newLength - 1, i) then
BEGIN
addRight := 1;
long := Munger(newText, newLength, NIL, 0, @space[1], 1);
FailMemError;
newLength := newLength + 1;
END;
END
else
if IsBlank(newText^, newLength-1, i) then
BEGIN
delRight := i;
long := Munger(newText, newLength-1, NIL,i, @space[1],0);
FailMemError;
newLength := newLength - i;
END;
END;
{ **************************************************************************** }
IF newLength > 0 THEN
BEGIN
{$IFC qDebug}
IF dataType <> 'TEXT' THEN
ProgramBreak('TEPasteCommand given some non-text from clipboard')
ELSE
{$ENDC}
BEGIN { Prime "new" values }
fNewText := newText;
fNewStart := fHTE^^.selStart;
fNewEnd := fNewStart + newLength;
fTextPad := newLength - (fOldEnd - fOldStart);
IF itsTEView.fStyleType = kWithStyle THEN
BEGIN
newStyleLen := gClipView.GivePasteData(Handle(newStyles), 'styl');
{$IFC SubSuper}
IF itsTEView.fAllowSubSuper THEN
newSubSuperLen := gClipView.GivePasteData(Handle(newSubSuper), kSubSuperClipType);
{$ENDC}
{ **************************************************************************** }
IF newStyleLen > 0 then
WITH newStyles^^ DO
{ Note: the scrpStyleTab is indexed [0..scrpNStyles-1], not [0..scrpNStyles] }
BEGIN
if addLeft > 0 then
FOR i := 1 TO scrpNStyles - 1 DO
scrpStyleTab[i].scrpStartChar := scrpStyleTab[i].scrpStartChar + addLeft
else if delLeft > 0 then
BEGIN
j := 0;
WHILE (j < scrpNStyles - 1) & (scrpStyleTab[j + 1].scrpStartChar <= delLeft) DO
j := j + 1;
if j > 0 then
BEGIN
FOR i := 0 TO scrpNStyles - 1 - j DO
scrpStyleTab[i] := scrpStyleTab[i + j];
scrpStyleTab[0].scrpStartChar := 0;
scrpNStyles := scrpNStyles - j;
END;
FOR i := 1 TO scrpNStyles - 1 DO
WITH scrpStyleTab[i] DO
scrpStartChar := scrpStartChar - delLeft;
END;
if delRight > 0 then
BEGIN
j := scrpNStyles - 1;
WHILE scrpStyleTab[j].scrpStartChar >= newLength DO
j := j - 1;
scrpNStyles := j + 1;
END;
END;
{$IFC SubSuper}
IF newSubSuperLen > 0 then
WITH newSubSuper^^ DO
BEGIN
if addLeft > 0 then
FOR i := 1 TO nRuns DO
runs[i].startChar := runs[i].startChar + addLeft
else if delLeft > 0 then
BEGIN
j := 1;
WHILE runs[j].startChar <= delLeft DO
j := j + 1;
if j > 1 then
BEGIN
FOR i := 0 TO nRuns - j DO
runs[i] := runs[i + j];
runs[0].startChar := 0;
nRuns := nRuns - j;
END;
FOR i := 1 TO nRuns DO
runs[i].startChar := runs[i].startChar - delLeft;
END;
if addRight > 0 then
runs[nRuns].startChar :=
runs[nRuns].startChar + addRight
else if delRight > 0 then
BEGIN
j := nRuns - 1;
WHILE runs[j].startChar >= newLength DO
j := j - 1;
nRuns := j + 1;
runs[nRuns].startChar := newLength + 1;
END;
END;
{$ENDC}
{ **************************************************************************** }
IF newStyleLen > 0 THEN
BEGIN
fNewStyles := newStyles;
fStylePad := { Difference between old and new styles }
newStyleLen - fStylePad;
END
ELSE
Handle(newStyles) := DisposeIfHandle(newStyles);
{$IFC SubSuper}
IF newSubSuperLen > 0 THEN
fNewSubSuper := newSubSuper
ELSE
Handle(newSubSuper) := DisposeIfHandle(newSubSuper);
{$ENDC}
END;
SetPermHandleSize(fPadding, MAX(fTextPad + fStylePad, 0));
FailSpaceIsLow;
END;
END
ELSE
BEGIN
newText := DisposeIfHandle(newText);
Handle(newStyles) := DisposeIfHandle(Handle(newStyles));
{$IFC SubSuper}
Handle(newSubSuper) := DisposeIfHandle(newSubSuper);
{$ENDC}
END;
Success(fi);
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S FullTERes}
PROCEDURE TFullTEPasteCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TFullTEPasteCommand', NIL, bClass);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC MenuAccess}
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TJustCommand.IJustCommand(itsTEView: TTEView; itsNewJust: INTEGER);
BEGIN
ICommand(cJustChange, itsTEView.fDocument, NIL, NIL);
fTEView := itsTEView;
fOldJust := itsTEView.fJustification;
fNewJust := itsNewJust;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TJustCommand.DoIt; OVERRIDE;
BEGIN
fTEView.SetJustification(fNewJust, kRedraw);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TJustCommand.RedoIt; OVERRIDE;
BEGIN
DoIt;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TJustCommand.UndoIt; OVERRIDE;
BEGIN
fTEView.SetJustification(fOldJust, kRedraw);
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S AFields}
PROCEDURE TJustCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TJustCommand', NIL, bClass);
DoToField('fTEView', @fTEView, bObject);
DoToField('fOldJust', @fOldJust, bInteger);
DoToField('fNewJust', @fNewJust, bInteger);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{$ENDC} {MenuAccess}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$IFC SubSuper}
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.ITETypingCommand(itsTEView: TTEView; itsFirstChar: Char);
{ no changes from TTETypingCommand }
VAR
fi: FailInfo;
PROCEDURE HdlInitFailed(error: OSErr; message: LONGINT);
BEGIN
Free;
END;
BEGIN
ITECommand(itsTEView, cTyping, TRUE);
CatchFailures(fi, HdlInitFailed);
fNewStart := fHTE^^.selStart; { Start and end are the same }
fNewEnd := fNewStart;
fNewText := NewPermHandle(0); { Allocate an empty block for text }
FailNIL(fNewText);
fCompleted := FALSE; { We've only just begun… }
fFirstChar := itsFirstChar; { Save character for Doit }
Success(fi);
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.Free; OVERRIDE;
{ change fTypingCommand to fFullTypingCommand }
BEGIN
IF TFullTEView(fTEView).fFullTypingCommand = SELF THEN
TFullTEView(fTEView).fFullTypingCommand := NIL;
INHERITED Free;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.DoNormalChar(aChar: Char);
{ no changes from TTETypingCommand }
BEGIN
FailOSErr(PtrAndHand(Ptr(SUCC(ORD(@aChar))), { Append char to end of fNewText }
fNewText, 1));
fNewEnd := SUCC(fNewEnd); { Bump both end of "selection" }
fTextPad := SUCC(fTextPad); { …and padding value }
SetHandleSize(fPadding, { This SetHandleSize can't grow the handle,
}
MAX( - (fTextPad + fStylePad), 0)); { …so it shouldn't fail. }
FailMemError;
END;
{--------------------------------------------------------------------------------------------------}
{ User has backspaced to the left of the original starting point. First, copy the
character (which may be more than one byte long if we are using a non-Roman script)
to a temporary buffer. The assumption is that no character will ever be longer
than four bytes. Sorry, folks, MacApp does not support typing in any script with
more than 4 billion characters.
Next, copy the character to the front of fOldText, and adjust fOldStart, fNewStart,
and fNewEnd. Note that we do NOT check for MemSpaceIsLow, since we want to let the
user delete characters. }
{$S FullTERes}
PROCEDURE TFullTETypingCommand.BkSpcLeft(theText: Handle; curStart: INTEGER);
TYPE
TSPtr = ^TextStyle;
VAR
savedSize: INTEGER;
theHeight: INTEGER;
theAscent: INTEGER;
oldSize: LONGINT;
whoCares: LONGINT;
aTextStyle: TSPtr;
savedChar: PACKED ARRAY [0..3] OF Char;
delStyle: TextStyle;
delSubSuper: SubOrSuper;
delBaseSize: INTEGER;
{$IFC qDebug}
savedPerm: BOOLEAN;
{$ENDC}
BEGIN
savedSize := 1;
IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
WHILE CharByte(theText^, curStart - savedSize) > 0 DO
savedSize := SUCC(savedSize);
curStart := curStart - savedSize;
{$IFC qDebug}
IF savedSize > 4 THEN
ProgramBreak('Character > 4 bytes');
{$ENDC}
IF savedSize = 1 THEN { Slight speed optimization for normal case
}
{$Push} {$R-}
savedChar[0] := CharsHandle(theText)^^[curStart]
{$Pop}
ELSE
BlockMove(Ptr(ORD(theText^) + curStart), @savedChar, savedSize);
IF fTEView.fStyleType = kWithStyle THEN { Only do this if styles are around }
BEGIN
TEGetStyle(curStart, delStyle, { Get the style of the deleted character }
theHeight, theAscent, fHTE); { (1 or 4 bytes, it's all only one style) }
IF NOT EqualBlocks(@delStyle, { If style doesn't match first in the list }
@fOldStyles^^.scrpStyleTab[0].scrpFont, SIZEOF(TextStyle)) THEN
BEGIN { …then insert new style at head of list }
fTEView.fSpecsChanged := TRUE; { User backspaced into new style! }
oldSize := { Make room for the new style element }
GetHandleSize(Handle(fOldStyles));
SetHandleSize(Handle(fOldStyles), oldSize + SIZEOF(ScrpSTElement));
FailMemError;
fStylePad := fStylePad + SIZEOF(ScrpSTElement);
{$Push} {$H-}
WITH fOldStyles^^.scrpStyleTab[0] DO
BlockMove(@scrpStartChar, { Move entire array up one element's size }
Ptr(ORD(@scrpStartChar) + SIZEOF(ScrpSTElement)), oldSize -
SIZEOF(fOldStyles^^.scrpNStyles));
{$Pop}
fOldStyles^^.scrpNStyles := { One more style }
SUCC(fOldStyles^^.scrpNStyles);
WITH fOldStyles^^.scrpStyleTab[0] DO
BEGIN
scrpHeight := theHeight; { Fill in the blanks }
scrpAscent := theAscent;
aTextStyle := TSPtr(@scrpFont);
aTextStyle^ := delStyle;
END;
END;
WITH fOldStyles^^.scrpStyleTab[0] DO
scrpStartChar := { PRED(scrpStartChar); } { Regardless, back off offset by one }
scrpStartChar - savedSize; { <- correction! }
END;
{******************************************************************************}
IF TFullTEView(fTEView).fAllowSubSuper THEN
BEGIN
TFullTEView(fTEView).GetSubSuper(curStart, delSubSuper, delBaseSize);
IF delSubSuper <> fOldSubSuper^^.runs[0].subSuper THEN
BEGIN
fTEView.fSpecsChanged := TRUE; { User backspaced into new sub/super! }
oldSize := { Make room for the new subsuper element }
GetHandleSize(Handle(fOldSubSuper));
SetHandleSize(Handle(fOldSubSuper), oldSize + SIZEOF(SubSuperElement));
FailMemError;
{$Push} {$H-}
WITH fOldSubSuper^^.runs[0] DO
BlockMove(@startChar, { Move entire array up one element's size }
Ptr(ORD(@startChar) + SIZEOF(SubSuperElement)), oldSize -
SIZEOF(fOldSubSuper^^.previousDrawProc) -
SIZEOF(fOldSubSuper^^.nRuns) - SIZEOF(fOldSubSuper^^.nullSubSuper) -
SIZEOF(fOldSubSuper^^.nullBaseSize));
{$Pop}
WITH fOldSubSuper^^ DO
nRuns := SUCC(nRuns);
fOldSubSuper^^.runs[0].subSuper := delSubSuper;
fOldSubSuper^^.runs[0].baseSize := delBaseSize;
END;
WITH fOldSubSuper^^.runs[0] DO
startChar := startChar - savedSize; { Regardless, back off offset by one }
END;
{******************************************************************************}
SetHandleSize(fPadding, GetHandleSize(fOldText) + savedSize + fStylePad);
FailMemError;
whoCares := Munger(fOldText, 0, NIL, 0, @savedChar, savedSize);
FailMemError;
fOldStart := curStart; { Treat this as though original selection }
fNewStart := curStart; { …had included this character }
fNewEnd := curStart;
fTextPad := fTextPad - savedSize;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.BkSpcRight(theText: Handle; curStart: INTEGER);
{ no change from TTETypingCommand }
VAR
savedSize: INTEGER;
BEGIN
savedSize := 1;
IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
WHILE CharByte(theText^, curStart - savedSize) > 0 DO
savedSize := SUCC(savedSize);
SetHandleSize(fPadding, MAX( - (fTextPad - savedSize + fStylePad), 0));
FailMemError;
fNewEnd := fNewEnd - savedSize;
fTextPad := fTextPad - savedSize;
SetHandleSize(fNewText, fNewEnd - fNewStart); { Shouldn't fail as we're only shrinking it
}
FailMemError;
END;
{--------------------------------------------------------------------------------------------------}
{ Forward delete (TTETypingCommand) courtesy of: Larry Goldman. Used by permission. }
{$S FullTERes}
PROCEDURE TFullTETypingCommand.FwdDelete(theText: Handle; curStart, curEnd: INTEGER);
TYPE
TSPtr = ^TextStyle;
VAR
savedSize: INTEGER;
theHeight: INTEGER;
theAscent: INTEGER;
oldSize: LONGINT;
whoCares: LONGINT;
aTextStyle: TSPtr;
savedChar: PACKED ARRAY [0..3] OF Char;
delStyle: TextStyle;
delSubSuper: SubOrSuper;
delBaseSize: INTEGER;
textSize: LONGINT;
oldTextSize: LONGINT;
BEGIN
textSize := GetHandleSize(theText);
IF (curStart = curEnd) & (curStart < textSize) THEN
BEGIN
savedSize := 0; {Get the complete character}
IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
WHILE (curStart + savedSize <= textSize) & (CharByte(theText^, curStart + savedSize) >
0) DO
savedSize := SUCC(savedSize);
savedSize := savedSize + 1;
{$IFC qDebug}
IF savedSize > 4 THEN
ProgramBreak('Character > 4 bytes');
{$ENDC}
IF savedSize = 1 THEN { Slight speed optimization for normal case
}
{$Push} {$R-}
savedChar[0] := CharsHandle(theText)^^[curStart]
{$Pop}
ELSE
BlockMove(Ptr(ORD(theText^) + curStart), @savedChar, savedSize);
IF (curStart >= fNewStart) & (curStart < fNewEnd) THEN { char is within fNewText }
BEGIN {Remove the char from fNewText and update
fNewEnd and fTextPad}
SetHandleSize(fPadding, MAX( - (fTextPad - savedSize + fStylePad), 0));
FailMemError;
fNewEnd := fNewEnd - savedSize;
fTextPad := fTextPad - savedSize;
{ Shouldn't fail as we're only shrinking it }
whoCares := Munger(fNewText, curStart - fNewStart, NIL, savedSize, @savedChar, 0);
FailMemError;
END
ELSE { add char to the end of fOldChars, don't
update fOldEnd, but update fPadding }
BEGIN { why NOT update fOldEnd??? - DWG}
oldTextSize := GetHandleSize(fOldText);
IF fTEView.fStyleType = kWithStyle THEN { Only do this if styles are around }
BEGIN
TEGetStyle(curStart, delStyle, { Get the style of the deleted character }
theHeight, theAscent, fHTE); { (1 or 4 bytes, it's all only one style) }
IF NOT EqualBlocks(@delStyle, { If style doesn't match last in the list }
@fOldStyles^^.scrpStyleTab[fOldStyles^^.scrpNStyles -
1].scrpFont, SIZEOF(TextStyle)) THEN
BEGIN { …then insert new style at end of list }
fTEView.fSpecsChanged := TRUE; { User backspaced into new style! }
oldSize := { Make room for the new style element }
GetHandleSize(Handle(fOldStyles));
SetHandleSize(Handle(fOldStyles), oldSize + SIZEOF(ScrpSTElement));
FailMemError;
fStylePad := fStylePad + SIZEOF(ScrpSTElement);
fOldStyles^^.scrpNStyles := { One more style }
SUCC(fOldStyles^^.scrpNStyles);
WITH fOldStyles^^.scrpStyleTab[fOldStyles^^.scrpNStyles - 1] DO
BEGIN
scrpStartChar := oldTextSize;
scrpHeight := theHeight; { Fill in the blanks }
scrpAscent := theAscent;
aTextStyle := TSPtr(@scrpFont);
aTextStyle^ := delStyle;
END;
END;
END;
{*******************************************************************************}
IF TFullTEView(fTEView).fAllowSubSuper THEN
BEGIN
TFullTEView(fTEView).GetSubSuper(curStart, delSubSuper, delBaseSize);
IF delSubSuper <> fOldSubSuper^^.runs[fOldSubSuper^^.nRuns - 1].subSuper THEN
BEGIN
fTEView.fSpecsChanged := TRUE; { User backspaced into new sub/super! }
oldSize := { Make room for the new subsuper element }
GetHandleSize(Handle(fOldSubSuper));
SetHandleSize(Handle(fOldSubSuper), oldSize + SIZEOF(SubSuperElement));
FailMemError;
WITH fOldSubSuper^^ DO
BEGIN
nRuns := SUCC(nRuns);
runs[nRuns] := runs[nRuns - 1];
WITH runs[nRuns] DO
startChar := oldTextSize + savedSize;
END;
WITH fOldSubSuper^^.runs[fOldSubSuper^^.nRuns - 1] DO
BEGIN
startChar := oldTextSize;
subSuper := delSubSuper;
baseSize := delBaseSize;
END;
END;
END;
{*******************************************************************************}
SetHandleSize(fPadding, oldTextSize + savedSize + fStylePad);
FailMemError;
whoCares := Munger(fOldText, oldTextSize, NIL, 0, @savedChar, savedSize);
FailMemError;
fTextPad := fTextPad - savedSize;
fOldEnd := fOldEnd + savedSize; { why not??? -DWG }
END;
END;
END;
{--------------------------------------------------------------------------------------------------}
{ ??? All this handle munging is expensive. Better would be to accumulate memory in
"chunks" of, say, 16 bytes so that this checking need not happen every time through.
Fortunately, the normal cases are not that bad. }
{$S FullTERes}
PROCEDURE TFullTETypingCommand.AddCharacter(aChar: Char);
VAR
theText: Handle;
curSelStart: INTEGER;
curSelEnd: INTEGER;
savedPerm: BOOLEAN;
fi: FailInfo;
index: INTEGER;
i: INTEGER;
PROCEDURE HdlCharFailed(error: OSErr; message: LONGINT);
BEGIN
savedPerm := PermAllocation(savedPerm);
END;
BEGIN
fView.Update; { Makes sure that all of TE's actions are
Visible }
IF fView.Focus THEN;
WITH fHTE^^ DO { Get handy info about the text handle }
BEGIN
curSelStart := selStart;
curSelEnd := selEnd;
theText := hText;
END;
CatchFailures(fi, HdlCharFailed);
savedPerm := PermAllocation(TRUE);
{ Update the fNewText handle and other information. Note that because of backspace,
this can be tricky.}
IF (aChar = chFwdDelete) THEN
FwdDelete(theText, curSelStart, curSelEnd) { User types forward delete, so keep in
synch}
ELSE IF aChar <> chBackspace THEN { Not a backspace. Do the right thing }
DoNormalChar(aChar)
ELSE IF (curSelStart <= fOldStart) & { User typed backspace so keep in synch }
(curSelStart > 0) & (curSelStart = curSelEnd) THEN
BkSpcLeft(theText, curSelStart) { Handle backspace to left of start }
ELSE IF fNewEnd > fNewStart THEN { Delete 1 character from end of fNewText }
BkSpcRight(theText, curSelStart); { Handle backspace to right of start }
savedPerm := PermAllocation(savedPerm);
Success(fi);
IF aChar <> chFwdDelete THEN
{ Let TextEdit have the character, as either 1) we're adding a byte, so we know there
is a reserve tank, so the worst this will do is eat into it a little, or 2) we're
deleting a character, which can only decrease memory usage. }
BEGIN
IF TFullTEView(fTEView).fAllowSubSuper THEN
IF aChar = chBackspace THEN
{ DeleteSubSuperChars will check for multi-byte characters... }
TFullTEView(fTEView).DeleteSubSuperChars(MIN(curSelStart, curSelEnd - 1), curSelEnd)
ELSE
{ If I'm reading everything correctly, a multi-byte character will still }
{ only get to AddCharacter one byte at a time, so this should be okay... }
TFullTEView(fTEView).InsertSubSuperChars(curSelStart, 1, fNewSubSuper);
TEKey(aChar, fHTE);
END
ELSE IF (curSelStart <> curSelEnd) THEN { forward delete with chars selected}
BEGIN
IF TFullTEView(fTEView).fAllowSubSuper THEN
TFullTEView(fTEView).DeleteSubSuperChars(curSelStart, curSelEnd);
TEDelete(fHTE);
END
ELSE IF (curSelStart < GetHandleSize(theText)) THEN
BEGIN { forward delete with insertion point}
TEKey(chRight, fHTE);
IF TFullTEView(fTEView).fAllowSubSuper THEN
{ DeleteSubSuperChars will check for multi-byte characters... }
TFullTEView(fTEView).DeleteSubSuperChars(curSelStart, curSelStart + 1);
TEKey(chBackspace, fHTE);
END;
fTEView.SynchView(kRedraw); { Now clean up the view. }
{$IFC qDebug}
IF pTEIntenseDebugging THEN
BEGIN
WrLblHandleContents('fOldText', fOldText);
WRITELN;
WrLblHandleContents('fNewText', fNewText);
WRITELN;
DumpTTECommand(SELF);
END;
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.DoIt; OVERRIDE;
{ no change from TTETypingCommand }
BEGIN
AddCharacter(fFirstChar);
{$IFC qDebug}
IF pTEIntenseDebugging THEN
DumpTTECommand(SELF);
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTETypingCommand.RedoIt; OVERRIDE;
VAR
currentStyle: TextStyle;
lineHeight: INTEGER;
fontAscent: INTEGER;
resetStyle: BOOLEAN;
theSubSuper: SubOrSuper;
theBaseSize: INTEGER;
resetSubSuper: BOOLEAN;
BEGIN
IF (fOldEnd - fOldStart) = GetHandleSize(fOldText) THEN
BEGIN { No chars were vacuumed}
resetStyle := FALSE;
IF (fTEView.fStyleType = kWithStyle) & (fOldEnd = fOldStart) THEN
BEGIN
TEGetStyle(fOldStart, currentStyle, lineHeight, fontAscent, fHTE);
resetStyle := NOT EqualBlocks(@currentStyle, @fOldStyles^^.scrpStyleTab[0].scrpFont,
SIZEOF(TextStyle));
END;
resetSubSuper := FALSE;
IF (TFullTEView(fTEView).fAllowSubSuper) & (fOldEnd = fOldStart) THEN
BEGIN
TFullTEView(fTEView).GetSubSuper(fOldStart, theSubSuper, theBaseSize);
resetSubSuper := (theSubSuper <> fOldSubSuper^^.runs[0].subSuper) |
(theBaseSize <> fOldSubSuper^^.runs[0].baseSize);
END;
IF resetStyle THEN { The new text has a style of its own }
fNewStyles := fOldStyles; { Make InstallNewText insert styles, too }
IF resetSubSuper THEN
fNewSubSuper := fOldSubSuper;
INHERITED RedoIt;
IF resetStyle THEN
fNewStyles := NIL; { So fNewStyles doesn't get disposed }
IF resetSubSuper THEN
fNewSubSuper := NIL;
END
ELSE
BEGIN
IF fTEView.Focus THEN; {??? What if Focus fails}
TESetSelect(fOldStart,
fOldStart + GetHandleSize(fOldText), fHTE); { select vacuumed chars, too }
TFullTEView(fTEView).DeleteSubSuperChars(fOldStart, fOldStart + GetHandleSize(fOldText));
TEDelete(fHTE); { Remove old text, including vacuumed chars}
SetHandleSize(fPadding, MAX( - (fTextPad + fStylePad), 0));
FailMemError;
InstallNewText;
fTEView.SynchView(kRedraw);
{$IFC qDebug}
IF pTEIntenseDebugging THEN
DumpTTECommand(SELF);
{$ENDC}
END;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTETypingCommand.UndoIt; OVERRIDE;
{ no changes from TTETypingCommand }
BEGIN
CompleteTyping;
INHERITED UndoIt;
END;
{--------------------------------------------------------------------------------------------------}
{$S FullTERes}
PROCEDURE TFullTETypingCommand.CompleteTyping;
VAR
i: INTEGER;
offset: LONGINT;
BEGIN
fCompleted := TRUE;
IF fTEView.fStyleType = kWithStyle THEN
WITH fOldStyles^^ DO
BEGIN
offset := - scrpStyleTab[0].scrpStartChar;
IF offset > 0 THEN
FOR i := 0 TO scrpNStyles - 1 DO
scrpStyleTab[i].scrpStartChar := scrpStyleTab[i].scrpStartChar + offset;
END;
IF TFullTEView(fTEView).fAllowSubSuper THEN
WITH fOldSubSuper^^ DO
BEGIN
offset := - runs[0].startChar;
IF offset > 0 THEN
FOR i := 0 to nRuns DO
runs[i].startChar := runs[i].startChar + offset;
END;
{$IFC qDebug}
IF pTEIntenseDebugging THEN
DumpTTECommand(SELF);
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTETypingCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
{ no change from TTETypingCommand }
BEGIN
DoToField('TFullTETypingCommand', NIL, bClass);
DoToField('fCompleted', @fCompleted, bBoolean);
DoToField('fFirstChar', @fFirstChar, bBoolean);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
{ No change from TTEStyleCommand }
PROCEDURE TFullTEStyleCommand.ITEStyleCommand(itsTEView: TTEView; itsNewStyle: TextStyle;
itsCmdNumber: CmdNumber; itsMode: INTEGER);
VAR
savedPerm: BOOLEAN;
fi: FailInfo;
BEGIN
ITECommand(itsTEView, itsCmdNumber, FALSE); { Perform stock initialization, sans text }
fOldTextStyle := itsTEView.fTextStyle;
fNewTextStyle := itsNewStyle;
fMode := itsMode;
IF qNeedsColorQD | gConfiguration.hasColorQD THEN
fMode := itsMode
ELSE
fMode := BAND(itsMode, BNOT(doColor));
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTEStyleCommand.InstallSubSuper(newSubSuper: SubSuperHandle);
VAR theStyle: TextStyle;
i: INTEGER;
theBaseSize: INTEGER;
BEGIN
IF newSubSuper <> NIL THEN
BEGIN
TFullTEView(fTEView).SetSubSuper(fOldStart, fOldEnd, newSubSuper, kDontRedraw);
MoveHHi(Handle(newSubSuper));
HLock(Handle(newSubSuper));
WITH newSubSuper^^ DO
FOR i := 0 TO nRuns - 1 DO
WITH runs[i] DO
IF subSuper <> normal THEN
BEGIN
theBaseSize := baseSize;
IF theBaseSize = 0 THEN theBaseSize := GetDefFontSize;
theStyle.tsSize := theBaseSize DIV 2;
SetSelect(fOldStart + startChar,
fOldStart + MIN(runs[i + 1].startChar, runs[nRuns].startChar - 1), fHTE);
TESetStyle(doSize, theStyle, kDontRedraw, fHTE);
END;
HUnlock(Handle(newSubSuper));
END;
SetSelect(fOldStart, fOldEnd, fHTE);
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTEStyleCommand.InstallOneStyle(newStyl: TextStyle; newSubSuper: SubSuperHandle);
VAR aRect: Rect;
BEGIN
fTEView.SetOneStyle(fOldStart, fOldEnd, fMode, newStyl, kDontRedraw); { Focus'es for us }
IF TFullTEView(fTEView).fAllowSubSuper THEN
InstallSubSuper(newSubSuper);
fTEView.RecalcText; { Might have changed number of lines }
{ and now, finally, we'll Redraw... }
IF TFullTEView(fTEView).fAllowSubSuper THEN
BEGIN
fTEView.GetQDExtent(aRect);
TEUpdate(aRect, fHTE);
END;
fTEView.SynchView(NOT TFullTEView(fTEView).fAllowSubSuper);
fTEView.fSpecsChanged := TRUE;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTEStyleCommand.InstallManyStyles(newStyls: StScrpHandle; newSubSuper: SubSuperHandle);
VAR aRect: Rect;
BEGIN
IF fTEView.Focus THEN;
{ No need to check for fStyleType, since we only get here if the record is stylish }
SetStylScrap(fOldStart, fOldEnd, newStyls, kDontRedraw, fHTE);
IF TFullTEView(fTEView).fAllowSubSuper THEN
InstallSubSuper(newSubSuper);
fTEView.RecalcText; { Might have changed number of lines }
{ and now, finally, we'll Redraw... }
IF TFullTEView(fTEView).fAllowSubSuper THEN
BEGIN
fTEView.GetQDExtent(aRect);
TEUpdate(aRect, fHTE);
END;
fTEView.SynchView(NOT TFullTEView(fTEView).fAllowSubSuper);
fTEView.fSpecsChanged := TRUE;
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTEStyleCommand.DoIt; OVERRIDE;
VAR
aTextStyle: TextStyle;
aSubSuper: SubSuperHandle;
i: INTEGER;
theBaseSize: INTEGER;
BEGIN
aTextStyle := fNewTextStyle;
aSubSuper := fNewSubSuper;
IF aSubSuper = NIL THEN aSubSuper := fOldSubSuper;
IF TFullTEView(fTEView).fAllowSubSuper & (fCmdNumber = cSizeChange) THEN
BEGIN
WITH aSubSuper^^ DO
FOR i := 0 TO nRuns - 1 DO
IF BAND(fMode, doSize) <> 0 THEN
runs[i].baseSize := aTextStyle.tsSize
ELSE IF BAND(fMode, addSize) <> 0 THEN
BEGIN
theBaseSize := runs[i].baseSize;
if theBaseSize = 0 then theBaseSize := GetDefFontSize;
runs[i].baseSize := theBaseSize + aTextStyle.tsSize;
END;
END;
InstallOneStyle(aTextStyle, aSubSuper);
fMode := BAND(fMode, BNOT(doToggle)); { Turn off toggle mode, if set }
{$IFC qDebug}
IF pTEIntenseDebugging THEN
DumpTTECommand(SELF);
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
PROCEDURE TFullTEStyleCommand.UndoIt; OVERRIDE;
VAR
aTextStyle: TextStyle;
BEGIN
RestoreSelection;
IF fTEView.fStyleType = kWithoutStyle THEN
BEGIN
aTextStyle := fOldTextStyle;
InstallOneStyle(aTextStyle, fOldSubSuper)
END
ELSE
InstallManyStyles(fOldStyles, fOldSubSuper);
{$IFC qDebug}
IF pTEIntenseDebugging THEN
DumpTTECommand(SELF);
{$ENDC}
END;
{--------------------------------------------------------------------------------------------------}
{$S TEDoCommand}
{ No change from TTEStyleCommand }
PROCEDURE TFullTEStyleCommand.RedoIt; OVERRIDE;
BEGIN
RestoreSelection;
DoIt;
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
{ No change from TTEStyleCommand }
PROCEDURE TFullTEStyleCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TFullTEStyleCommand', NIL, bClass);
DoToField('fMode', @fMode, bInteger);
{$Push} {$H-}
TextStyleFields('fOldTextStyle', fOldTextStyle, DoToField);
TextStyleFields('fNewTextStyle', fNewTextStyle, DoToField);
{$Pop}
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}
{$S TESelCommand}
PROCEDURE TFullTESubSuperCommand.ITFullTESubSuperCommand(itsTEView: TFullTEView; itsCmdNumber: CmdNumber);
VAR aSubSuperHandle: SubSuperHandle;
oldStyles: StScrpHandle;
which, oldWhich: SubOrSuper;
i: INTEGER;
theBaseSize: INTEGER;
newStyle: TextStyle;
mode: INTEGER;
startOfSelection: INTEGER;
endOfSelection: INTEGER;
BEGIN
aSubSuperHandle := itsTEView.GetSubSuperHandle;
FailNIL(aSubSuperHandle);
WITH itsTEView.fHTE^^ DO
BEGIN
startOfSelection := selStart;
endOfSelection := selEnd;
END;
if itsCmdNumber = cSubscript then
which := subscript
else if itsCmdNumber = cSuperscript then
which := superscript
else
which := normal;
if which <> normal then
if itsTEView.ContinuousSubSuper(startOfSelection, endOfSelection, oldWhich, theBaseSize)
& (oldWhich = which) then
which := normal { toggle sub/superscript back to normal }
else
oldWhich := undefined
else
oldWhich := undefined;
if oldWhich = undefined then
BEGIN
theBaseSize := 0;
oldStyles := GetStylScrap(itsTEView.fHTE);
FailNIL(oldStyles);
WITH oldStyles^^ DO
FOR i := 0 TO scrpNStyles - 1 DO
theBaseSize := MAX(scrpStyleTab[i].scrpSize , theBaseSize);
DisposHandle(Handle(oldStyles));
WITH aSubSuperHandle^^ DO
FOR i := 0 TO nRuns - 1 DO
theBaseSize := MAX(runs[i].baseSize, theBaseSize);
if theBaseSize = 0 then theBaseSize := GetDefFontSize;
END
else
theBaseSize := itsTEView.fSubSuperHandle^^.runs[
GetIndex(itsTEView.fSubSuperHandle, startOfSelection)].baseSize;
if which = normal then
newStyle.tsSize := theBaseSize
else
newStyle.tsSize := theBaseSize DIV 2;
if itsCmdNumber = cPlainText then
BEGIN
newStyle.tsFace := [];
mode := doSize + doFace;
END
else
mode := doSize;
ITEStyleCommand(itsTEView, newStyle, cStyleChange, mode);
fNewSubSuper := aSubSuperHandle;
WITH fNewSubSuper^^ DO
FOR i := 0 TO nRuns - 1 DO
BEGIN
runs[i].subSuper := which;
runs[i].baseSize := theBaseSize;
END;
END;
{--------------------------------------------------------------------------------------------------}
{$IFC qDebug}
{$S TEFields}
PROCEDURE TFullTESubSuperCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: INTEGER)); OVERRIDE;
BEGIN
DoToField('TTFullTESubSuperCommand', NIL, bClass);
INHERITED Fields(DoToField);
END;
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{$ENDC}
{--------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------}